summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichiro Den <den@valinux.co.jp>2026-08-21 02:34:36 +0900
committerVinod Koul <vkoul@kernel.org>2026-09-09 19:06:51 +0530
commit080b8cfa01bc86e5c601ff625a34bec30cf08156 (patch)
tree7f5f6c42315c1f5c3c60dce4d9d174401b98346d
parent8d249a120ce615804edab065ef4d157dbc92125f (diff)
downloadlinux-next-080b8cfa01bc86e5c601ff625a34bec30cf08156.tar.gz
linux-next-080b8cfa01bc86e5c601ff625a34bec30cf08156.zip
dmaengine: dw-edma: Centralize LL doorbell decisions
LL fill currently rings the doorbell every time. A running eDMA or HDMA channel follows entries whose CB matches CCS without another kick. A channel stopped at a CB mismatch needs one. Move that decision to dw_edma_core_ch_maybe_doorbell(). It rings only for a BUSY LL channel with pending entries, no EDMA_REQ_STOP or EDMA_REQ_PAUSE. The BUSY check prevents EDMA_REQ_STOP completion from restarting terminated work. issue_pending() still publishes LL entries only from IDLE. A later patch allows live appends. Non-LL channels are unchanged. Reviewed-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Koichiro Den <den@valinux.co.jp> Link: https://patch.msgid.link/20260820173439.2004068-8-den@valinux.co.jp Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 3c1f3f728875..5a8407ca68a2 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -167,8 +167,6 @@ static void dw_edma_core_ll_start(struct dw_edma_desc *desc)
desc->done_burst = desc->start_burst;
desc->start_burst = i;
-
- dw_edma_core_ch_doorbell(chan);
}
static void dw_edma_core_start(struct dw_edma_desc *desc)
@@ -249,6 +247,16 @@ static void dw_edma_finish_termination(struct dw_edma_chan *chan)
chan->status = EDMA_ST_IDLE;
}
+/* Must be called with vc.lock held. */
+static void dw_edma_core_ch_maybe_doorbell(struct dw_edma_chan *chan)
+{
+ if (chan->non_ll || chan->request != EDMA_REQ_NONE ||
+ chan->status != EDMA_ST_BUSY || !dw_edma_ll_pending(chan))
+ return;
+
+ dw_edma_core_ch_doorbell(chan);
+}
+
static void dw_edma_device_caps(struct dma_chan *dchan,
struct dma_slave_caps *caps)
{
@@ -374,6 +382,7 @@ static int dw_edma_device_resume(struct dma_chan *dchan)
chan->status = EDMA_ST_BUSY;
if (!dw_edma_start_transfer(chan))
chan->status = EDMA_ST_IDLE;
+ dw_edma_core_ch_maybe_doorbell(chan);
}
return err;
@@ -420,6 +429,7 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan)
chan->status == EDMA_ST_IDLE) {
chan->status = EDMA_ST_BUSY;
dw_edma_start_transfer(chan);
+ dw_edma_core_ch_maybe_doorbell(chan);
}
spin_unlock_irqrestore(&chan->vc.lock, flags);
}
@@ -733,6 +743,8 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
default:
break;
}
+ dw_edma_core_ch_maybe_doorbell(chan);
+
spin_unlock_irqrestore(&chan->vc.lock, flags);
}