[PATCH v2 29/64] dmaengine: sf-pdma: route error callbacks through channel BH
From: Allen Pais
Date: Mon Jul 27 2026 - 16:36:49 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 6f79cc28703e..a6c2f53f005e 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);
- tasklet_kill(&ch->vchan.task);
tasklet_kill(&ch->done_tasklet);
tasklet_kill(&ch->err_tasklet);
+ dma_chan_kill_bh(&ch->vchan.chan);
}
if (pdev->dev.of_node)
--
2.43.0