[PATCH v3 28/34] dmaengine: sf-pdma: route error callbacks through channel BH

Frank Li Frank.li at oss.nxp.com
Wed Sep 2 08:39:38 PDT 2026


On Mon, Aug 10, 2026 at 11:09:29AM -0700, Allen Pais wrote:
> virt-dma now dispatches completion callbacks through per-channel BH work,
> but SF-PDMA invokes the client callback directly from its error tasklet
> after exhausting its retries.
>
> Complete failed descriptors through virt-dma with an aborted result and
> the remaining transfer size, then start the next pending transfer. During
> removal, kill the producer tasklets before the channel BH so they cannot
> enqueue callback work after it has been canceled.
>
> Signed-off-by: Allen Pais <allen.lkml at gmail.com>
> ---
>  drivers/dma/sf-pdma/sf-pdma.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
> index a08ca355dadb..ab2029af0c0c 100644
> --- a/drivers/dma/sf-pdma/sf-pdma.c
> +++ b/drivers/dma/sf-pdma/sf-pdma.c
> @@ -328,7 +328,17 @@ static void sf_pdma_errbh_tasklet(struct tasklet_struct *t)
>  	if (chan->retries <= 0) {
>  		/* fail to recover */
>  		spin_unlock_irqrestore(&chan->lock, flags);
> -		dmaengine_desc_get_callback_invoke(desc->async_tx, NULL);
> +
> +		spin_lock_irqsave(&chan->vchan.lock, flags);
> +		list_del(&desc->vdesc.node);
> +		desc->vdesc.tx_result.result = DMA_TRANS_ABORTED;
> +		desc->vdesc.tx_result.residue = desc->xfer_size;
> +		vchan_cookie_complete(&desc->vdesc);
> +
> +		chan->desc = sf_pdma_get_first_pending_desc(chan);
> +		if (chan->desc)
> +			sf_pdma_xfer_desc(chan);
> +		spin_unlock_irqrestore(&chan->vchan.lock, flags);

I am not sure if logic is equal. It'd better someone can help test it.

Frank

>  	} else {
>  		/* retry */
>  		chan->retries--;
> @@ -602,9 +612,9 @@ static void sf_pdma_remove(struct platform_device *pdev)
>  		devm_free_irq(&pdev->dev, ch->txirq, ch);
>  		devm_free_irq(&pdev->dev, ch->errirq, ch);
>  		list_del(&ch->vchan.chan.device_node);
> -		dmaengine_kill_bh(&ch->vchan.chan);
>  		tasklet_kill(&ch->done_tasklet);
>  		tasklet_kill(&ch->err_tasklet);
> +		dmaengine_kill_bh(&ch->vchan.chan);
>  	}
>
>  	if (pdev->dev.of_node)
> --
> 2.43.0
>



More information about the linux-riscv mailing list