Re: [PATCH v3 28/34] dmaengine: sf-pdma: route error callbacks through channel BH
From: Frank Li
Date: Wed Sep 02 2026 - 11:55:42 EST
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@xxxxxxxxx>
> ---
> 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
>