[PATCH v3 28/34] dmaengine: sf-pdma: route error callbacks through channel BH
Allen Pais
allen.lkml at gmail.com
Mon Aug 10 11:09:29 PDT 2026
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);
} 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