Re: [PATCH v4 07/24] dmaengine: dw-edma: Centralize LL doorbell decisions

Frank Li <[email protected]> Wed, 29 Jul 2026 11:01:47 -0500
Newsgroups org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel
Message-ID <amoj6zAcRocJbbCY@SMW015318>
On Wed, Jul 29, 2026 at 11:30:19PM +0900, Koichiro Den wrote:
> 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.
>
> Signed-off-by: Koichiro Den <[email protected]>
> ---

Reviewed-by: Frank Li <[email protected]>

> Changes in v4:
>   - No changes.
>
>  drivers/dma/dw-edma/dw-edma-core.c | 16 ++++++++++++++--
>  1 file 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 b419ff2becf9..c036510dabcb 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);
>  }
>
> --
> 2.51.0
>