[PATCH v4 06/24] dmaengine: dw-edma: Dispatch DONE interrupts by channel request

From: Koichiro Den

Date: Wed Jul 29 2026 - 10:41:02 EST


Prepare for a later patch that reclaims LL progress before request handling
and can remove the last issued descriptor. Move the request switch outside
the common descriptor check.

Keep the existing per-request descriptor checks for now. That later patch
removes them when STOP/PAUSE handling becomes independent of the descriptor
list.

No functional change.

Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes in v4:
- Clarify that descriptor-independent STOP/PAUSE handling is added with
LL progress reclamation later, not by this prep patch. (Sashiko)

drivers/dma/dw-edma/dw-edma-core.c | 56 ++++++++++++++++--------------
1 file changed, 29 insertions(+), 27 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 6e7d1f7c20f9..b419ff2becf9 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -697,39 +697,41 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
return;
}

- vd = vchan_next_desc(&chan->vc);
- if (vd) {
- switch (chan->request) {
- case EDMA_REQ_NONE:
- case EDMA_REQ_PAUSE:
- desc = vd2dw_edma_desc(vd);
- if (desc->start_burst >= desc->nburst) {
- dw_hdma_set_callback_result(vd,
- DMA_TRANS_NOERROR);
- list_del(&vd->node);
- vchan_cookie_complete(vd);
- if (!chan->non_ll)
- chan->ll_done = chan->ll_head;
- }
+ switch (chan->request) {
+ case EDMA_REQ_NONE:
+ case EDMA_REQ_PAUSE:
+ vd = vchan_next_desc(&chan->vc);
+ if (!vd)
+ break;

- if (chan->request == EDMA_REQ_PAUSE) {
- chan->request = EDMA_REQ_NONE;
- chan->status = EDMA_ST_PAUSE;
- break;
- }
+ desc = vd2dw_edma_desc(vd);
+ if (desc->start_burst >= desc->nburst) {
+ dw_hdma_set_callback_result(vd, DMA_TRANS_NOERROR);
+ list_del(&vd->node);
+ vchan_cookie_complete(vd);
+ if (!chan->non_ll)
+ chan->ll_done = chan->ll_head;
+ }

- /* Continue transferring if there are remaining chunks or issued requests.
- */
- chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE;
+ if (chan->request == EDMA_REQ_PAUSE) {
+ chan->request = EDMA_REQ_NONE;
+ chan->status = EDMA_ST_PAUSE;
break;
+ }

- case EDMA_REQ_STOP:
- dw_edma_finish_termination(chan);
- break;
+ chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE;
+ break;

- default:
+ case EDMA_REQ_STOP:
+ vd = vchan_next_desc(&chan->vc);
+ if (!vd)
break;
- }
+
+ dw_edma_finish_termination(chan);
+ break;
+
+ default:
+ break;
}
spin_unlock_irqrestore(&chan->vc.lock, flags);
}
--
2.51.0