[PATCH v3 28/34] dmaengine: sf-pdma: route error callbacks through channel BH
From: Allen Pais
Date: Mon Aug 10 2026 - 14:16:41 EST
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);
} 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