Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 03/64] dmaengine: apple-admac: use dma_chan BH callback
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 04/64] dmaengine: at_xdmac: move irq bottom half to dma_chan BH Allen Pais
                     ` (17 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sven Peter, Janne Grunau, Neal Gompa, asahi, linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/apple-admac.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 14a5ee14a481..84483247bde6 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -89,7 +89,6 @@ struct admac_chan {
 	unsigned int no;
 	struct admac_data *host;
 	struct dma_chan chan;
-	struct tasklet_struct tasklet;
 
 	u32 carveout;
 
@@ -521,10 +520,7 @@ static int admac_terminate_all(struct dma_chan *chan)
 		list_add_tail(&adchan->current_tx->node, &adchan->to_free);
 		adchan->current_tx = NULL;
 	}
-	/*
-	 * Descriptors can only be freed after the tasklet
-	 * has been killed (in admac_synchronize).
-	 */
+	/* Descriptors are released once the BH is flushed in admac_synchronize */
 	list_splice_tail_init(&adchan->submitted, &adchan->to_free);
 	list_splice_tail_init(&adchan->issued, &adchan->to_free);
 	spin_unlock_irqrestore(&adchan->lock, flags);
@@ -543,7 +539,7 @@ static void admac_synchronize(struct dma_chan *chan)
 	list_splice_tail_init(&adchan->to_free, &head);
 	spin_unlock_irqrestore(&adchan->lock, flags);
 
-	tasklet_kill(&adchan->tasklet);
+	dma_chan_kill_bh(&adchan->chan);
 
 	list_for_each_entry_safe(adtx, _adtx, &head, node) {
 		list_del(&adtx->node);
@@ -662,7 +658,7 @@ static void admac_handle_status_desc_done(struct admac_data *ad, int channo)
 		tx->reclaimed_pos %= 2 * tx->buf_len;
 
 		admac_cyclic_write_desc(ad, channo, tx);
-		tasklet_schedule(&adchan->tasklet);
+		dma_chan_schedule_bh(&adchan->chan);
 	}
 	spin_unlock_irqrestore(&adchan->lock, flags);
 }
@@ -712,9 +708,9 @@ static irqreturn_t admac_interrupt(int irq, void *devid)
 	return IRQ_HANDLED;
 }
 
-static void admac_chan_tasklet(struct tasklet_struct *t)
+static void admac_chan_bh(struct dma_chan *chan)
 {
-	struct admac_chan *adchan = from_tasklet(adchan, t, tasklet);
+	struct admac_chan *adchan = to_admac_chan(chan);
 	struct admac_tx *adtx;
 	struct dmaengine_desc_callback cb;
 	struct dmaengine_result tx_result;
@@ -886,7 +882,7 @@ static int admac_probe(struct platform_device *pdev)
 		INIT_LIST_HEAD(&adchan->issued);
 		INIT_LIST_HEAD(&adchan->to_free);
 		list_add_tail(&adchan->chan.device_node, &dma->channels);
-		tasklet_setup(&adchan->tasklet, admac_chan_tasklet);
+		dma_chan_init_bh(&adchan->chan, admac_chan_bh);
 	}
 
 	err = reset_control_reset(ad->rstc);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 04/64] dmaengine: at_xdmac: move irq bottom half to dma_chan BH
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
  2026-07-27 20:28   ` [PATCH v2 03/64] dmaengine: apple-admac: use dma_chan BH callback Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 08/64] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
                     ` (16 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Ludovic Desroches, linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/at_xdmac.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 901971e8bae6..aa918043e37e 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -228,7 +228,6 @@ struct at_xdmac_chan {
 	u32				save_cndc;
 	u32				irq_status;
 	unsigned long			status;
-	struct tasklet_struct		tasklet;
 	struct dma_slave_config		sconfig;
 
 	spinlock_t			lock;
@@ -1759,9 +1758,9 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)
 	/* Then continue with usual descriptor management */
 }
 
-static void at_xdmac_tasklet(struct tasklet_struct *t)
+static void at_xdmac_tasklet(struct dma_chan *chan)
 {
-	struct at_xdmac_chan	*atchan = from_tasklet(atchan, t, tasklet);
+	struct at_xdmac_chan	*atchan = to_at_xdmac_chan(chan);
 	struct at_xdmac		*atxdmac = to_at_xdmac(atchan->chan.device);
 	struct at_xdmac_desc	*desc;
 	struct dma_async_tx_descriptor *txd;
@@ -1865,7 +1864,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
 			if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
 				at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
 
-			tasklet_schedule(&atchan->tasklet);
+			dma_chan_schedule_bh(&atchan->chan);
 			ret = IRQ_HANDLED;
 		}
 
@@ -2317,7 +2316,7 @@ static int at_xdmac_probe(struct platform_device *pdev)
 		return PTR_ERR(atxdmac->clk);
 	}
 
-	/* Do not use dev res to prevent races with tasklet */
+	/* Do not use devm resources to prevent races with the BH worker */
 	ret = request_irq(atxdmac->irq, at_xdmac_interrupt, 0, "at_xdmac", atxdmac);
 	if (ret) {
 		dev_err(&pdev->dev, "can't request irq\n");
@@ -2397,7 +2396,7 @@ static int at_xdmac_probe(struct platform_device *pdev)
 		spin_lock_init(&atchan->lock);
 		INIT_LIST_HEAD(&atchan->xfers_list);
 		INIT_LIST_HEAD(&atchan->free_descs_list);
-		tasklet_setup(&atchan->tasklet, at_xdmac_tasklet);
+		dma_chan_init_bh(&atchan->chan, at_xdmac_tasklet);
 
 		/* Clear pending interrupts. */
 		while (at_xdmac_chan_read(atchan, AT_XDMAC_CIS))
@@ -2458,7 +2457,7 @@ static void at_xdmac_remove(struct platform_device *pdev)
 	for (i = 0; i < atxdmac->dma.chancnt; i++) {
 		struct at_xdmac_chan *atchan = &atxdmac->chan[i];
 
-		tasklet_kill(&atchan->tasklet);
+		dma_chan_kill_bh(&atchan->chan);
 		at_xdmac_free_chan_resources(&atchan->chan);
 	}
 }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 08/64] dmaengine: imx-dma: flip per-chan tasklet to dma_chan BH
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
  2026-07-27 20:28   ` [PATCH v2 03/64] dmaengine: apple-admac: use dma_chan BH callback Allen Pais
  2026-07-27 20:28   ` [PATCH v2 04/64] dmaengine: at_xdmac: move irq bottom half to dma_chan BH Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 13/64] dmaengine: mxs-dma: use dma_chan BH scheduling Allen Pais
                     ` (15 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, imx,
	linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/imx-dma.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 81c6276436f8..3ff0bfbfa5ff 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -145,7 +145,6 @@ struct imxdma_channel {
 	struct imxdma_engine		*imxdma;
 	unsigned int			channel;
 
-	struct tasklet_struct		dma_tasklet;
 	struct list_head		ld_free;
 	struct list_head		ld_queue;
 	struct list_head		ld_active;
@@ -344,8 +343,8 @@ static void imxdma_watchdog(struct timer_list *t)
 
 	imx_dmav1_writel(imxdma, 0, DMA_CCR(channel));
 
-	/* Tasklet watchdog error handler */
-	tasklet_schedule(&imxdmac->dma_tasklet);
+	/* BH watchdog error handler */
+	dma_chan_schedule_bh(&imxdmac->chan);
 	dev_dbg(imxdma->dev, "channel %d: watchdog timeout!\n",
 		imxdmac->channel);
 }
@@ -390,8 +389,8 @@ static irqreturn_t imxdma_err_handler(int irq, void *dev_id)
 			imx_dmav1_writel(imxdma, 1 << i, DMA_DBOSR);
 			errcode |= IMX_DMA_ERR_BUFFER;
 		}
-		/* Tasklet error handler */
-		tasklet_schedule(&imxdma->channel[i].dma_tasklet);
+		/* BH error handler */
+		dma_chan_schedule_bh(&imxdma->channel[i].chan);
 
 		dev_warn(imxdma->dev,
 			 "DMA timeout on channel %d -%s%s%s%s\n", i,
@@ -448,8 +447,8 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
 			imx_dmav1_writel(imxdma, tmp, DMA_CCR(chno));
 
 			if (imxdma_chan_is_doing_cyclic(imxdmac))
-				/* Tasklet progression */
-				tasklet_schedule(&imxdmac->dma_tasklet);
+				/* BH progression */
+				dma_chan_schedule_bh(&imxdmac->chan);
 
 			return;
 		}
@@ -462,8 +461,8 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
 
 out:
 	imx_dmav1_writel(imxdma, 0, DMA_CCR(chno));
-	/* Tasklet irq */
-	tasklet_schedule(&imxdmac->dma_tasklet);
+	/* Schedule the IRQ BH */
+	dma_chan_schedule_bh(&imxdmac->chan);
 }
 
 static irqreturn_t dma_irq_handler(int irq, void *dev_id)
@@ -592,9 +591,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
 	return 0;
 }
 
-static void imxdma_tasklet(struct tasklet_struct *t)
+static void imxdma_tasklet(struct dma_chan *chan)
 {
-	struct imxdma_channel *imxdmac = from_tasklet(imxdmac, t, dma_tasklet);
+	struct imxdma_channel *imxdmac = container_of(chan, struct imxdma_channel,
+						      chan);
 	struct imxdma_engine *imxdma = imxdmac->imxdma;
 	struct imxdma_desc *desc, *next_desc;
 	unsigned long flags;
@@ -1142,7 +1142,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
 		INIT_LIST_HEAD(&imxdmac->ld_free);
 		INIT_LIST_HEAD(&imxdmac->ld_active);
 
-		tasklet_setup(&imxdmac->dma_tasklet, imxdma_tasklet);
+		dma_chan_init_bh(&imxdmac->chan, imxdma_tasklet);
 		imxdmac->chan.device = &imxdma->dma_device;
 		dma_cookie_init(&imxdmac->chan);
 		imxdmac->channel = i;
@@ -1211,7 +1211,7 @@ static void imxdma_free_irq(struct platform_device *pdev, struct imxdma_engine *
 		if (!is_imx1_dma(imxdma))
 			disable_irq(imxdmac->irq);
 
-		tasklet_kill(&imxdmac->dma_tasklet);
+		dma_chan_kill_bh(&imxdmac->chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 13/64] dmaengine: mxs-dma: use dma_chan BH scheduling
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (2 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 08/64] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH Allen Pais
                     ` (14 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, imx,
	linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/mxs-dma.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 7acb3d29dad3..8cecc0add82d 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -109,7 +109,6 @@ struct mxs_dma_chan {
 	struct mxs_dma_engine		*mxs_dma;
 	struct dma_chan			chan;
 	struct dma_async_tx_descriptor	desc;
-	struct tasklet_struct		tasklet;
 	unsigned int			chan_irq;
 	struct mxs_dma_ccw		*ccw;
 	dma_addr_t			ccw_phys;
@@ -300,9 +299,9 @@ static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	return dma_cookie_assign(tx);
 }
 
-static void mxs_dma_tasklet(struct tasklet_struct *t)
+static void mxs_dma_tasklet(struct dma_chan *chan)
 {
-	struct mxs_dma_chan *mxs_chan = from_tasklet(mxs_chan, t, tasklet);
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
 
 	dmaengine_desc_get_callback_invoke(&mxs_chan->desc, NULL);
 }
@@ -386,8 +385,8 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
 		dma_cookie_complete(&mxs_chan->desc);
 	}
 
-	/* schedule tasklet on this channel */
-	tasklet_schedule(&mxs_chan->tasklet);
+	/* schedule BH on this channel */
+	dma_chan_schedule_bh(&mxs_chan->chan);
 
 	return IRQ_HANDLED;
 }
@@ -781,7 +780,7 @@ static int mxs_dma_probe(struct platform_device *pdev)
 		mxs_chan->chan.device = &mxs_dma->dma_device;
 		dma_cookie_init(&mxs_chan->chan);
 
-		tasklet_setup(&mxs_chan->tasklet, mxs_dma_tasklet);
+		dma_chan_init_bh(&mxs_chan->chan, mxs_dma_tasklet);
 
 
 		/* Add the channel to mxs_chan list */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (3 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 13/64] dmaengine: mxs-dma: use dma_chan BH scheduling Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-28 19:33     ` Linus Walleij
  2026-07-27 20:28   ` [PATCH v2 19/64] dmaengine: xilinx-dma: use dma_chan BH instead of tasklets Allen Pais
                     ` (13 subsequent siblings)
  18 siblings, 1 reply; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Linus Walleij, linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/ste_dma40.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 0d9ffa3e2663..f279a093a81f 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -461,8 +461,6 @@ struct d40_base;
  * @phy_chan: Pointer to physical channel which this instance runs on. If this
  * point is NULL, then the channel is not allocated.
  * @chan: DMA engine handle.
- * @tasklet: Tasklet that gets scheduled from interrupt context to complete a
- * transfer and call client callback.
  * @client: Cliented owned descriptor list.
  * @pending_queue: Submitted jobs, to be issued by issue_pending()
  * @active: Active descriptor.
@@ -489,7 +487,6 @@ struct d40_chan {
 	bool				 busy;
 	struct d40_phy_res		*phy_chan;
 	struct dma_chan			 chan;
-	struct tasklet_struct		 tasklet;
 	struct list_head		 client;
 	struct list_head		 pending_queue;
 	struct list_head		 active;
@@ -1587,13 +1584,13 @@ static void dma_tc_handle(struct d40_chan *d40c)
 	}
 
 	d40c->pending_tx++;
-	tasklet_schedule(&d40c->tasklet);
+	dma_chan_schedule_bh(&d40c->chan);
 
 }
 
-static void dma_tasklet(struct tasklet_struct *t)
+static void dma_tasklet(struct dma_chan *chan)
 {
-	struct d40_chan *d40c = from_tasklet(d40c, t, tasklet);
+	struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
 	struct d40_desc *d40d;
 	unsigned long flags;
 	bool callback_active;
@@ -1641,7 +1638,7 @@ static void dma_tasklet(struct tasklet_struct *t)
 	d40c->pending_tx--;
 
 	if (d40c->pending_tx)
-		tasklet_schedule(&d40c->tasklet);
+		dma_chan_schedule_bh(&d40c->chan);
 
 	spin_unlock_irqrestore(&d40c->lock, flags);
 
@@ -2815,7 +2812,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
 		INIT_LIST_HEAD(&d40c->client);
 		INIT_LIST_HEAD(&d40c->prepare_queue);
 
-		tasklet_setup(&d40c->tasklet, dma_tasklet);
+		dma_chan_init_bh(&d40c->chan, dma_tasklet);
 
 		list_add_tail(&d40c->chan.device_node,
 			      &dma->channels);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 19/64] dmaengine: xilinx-dma: use dma_chan BH instead of tasklets
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (4 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 20/64] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
                     ` (12 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Michal Simek, Suraj Gupta, Marek Vasut, Folker Schwesinger,
	Tomi Valkeinen, Krzysztof Kozlowski, linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/xilinx_dma.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 404235c17353..bf9f22ed1265 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -402,7 +402,6 @@ struct xilinx_dma_tx_descriptor {
  * @err: Channel has errors
  * @idle: Check for channel idle
  * @terminating: Check for channel being synchronized by user
- * @tasklet: Cleanup work after irq
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
  * @desc_pendingcount: Descriptor pending count
@@ -441,7 +440,6 @@ struct xilinx_dma_chan {
 	bool err;
 	bool idle;
 	bool terminating;
-	struct tasklet_struct tasklet;
 	struct xilinx_vdma_config config;
 	bool flush_on_fsync;
 	u32 desc_pendingcount;
@@ -1115,11 +1113,12 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
 
 /**
  * xilinx_dma_do_tasklet - Schedule completion tasklet
- * @t: Pointer to the Xilinx DMA channel structure
+ * @c: Pointer to the Xilinx DMA channel structure
  */
-static void xilinx_dma_do_tasklet(struct tasklet_struct *t)
+static void xilinx_dma_do_tasklet(struct dma_chan *c)
 {
-	struct xilinx_dma_chan *chan = from_tasklet(chan, t, tasklet);
+	struct xilinx_dma_chan *chan = container_of(c,
+			struct xilinx_dma_chan, common);
 
 	xilinx_dma_chan_desc_cleanup(chan);
 }
@@ -1898,7 +1897,7 @@ static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data)
 		spin_unlock(&chan->lock);
 	}
 
-	tasklet_hi_schedule(&chan->tasklet);
+	dma_chan_schedule_bh(&chan->common);
 	return IRQ_HANDLED;
 }
 
@@ -1955,7 +1954,7 @@ static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
 		spin_unlock(&chan->lock);
 	}
 
-	tasklet_schedule(&chan->tasklet);
+	dma_chan_schedule_bh(&chan->common);
 	return IRQ_HANDLED;
 }
 
@@ -2654,7 +2653,7 @@ static void xilinx_dma_synchronize(struct dma_chan *dchan)
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 
-	tasklet_kill(&chan->tasklet);
+	dma_chan_kill_bh(&chan->common);
 }
 
 /**
@@ -2745,7 +2744,7 @@ static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
 	if (chan->irq > 0)
 		free_irq(chan->irq, chan);
 
-	tasklet_kill(&chan->tasklet);
+	dma_chan_kill_bh(&chan->common);
 
 	list_del(&chan->common.device_node);
 }
@@ -3075,8 +3074,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 			str_enabled_disabled(chan->has_sg));
 	}
 
-	/* Initialize the tasklet */
-	tasklet_setup(&chan->tasklet, xilinx_dma_do_tasklet);
+	dma_chan_init_bh(&chan->common, xilinx_dma_do_tasklet);
 
 	/*
 	 * Initialize the DMA channel and add it to the DMA engine channels
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 20/64] dmaengine: xilinx-dpdma: kill vchan BH on remove
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (5 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 19/64] dmaengine: xilinx-dma: use dma_chan BH instead of tasklets Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:28   ` [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH Allen Pais
                     ` (11 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Laurent Pinchart, Michal Simek, linux-arm-kernel

virt-dma now dispatches completion callbacks through per-channel BH
work. Cancel that work when removing a channel, while retaining the
driver's separate error-handling tasklet.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/xilinx_dpdma.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index d9a3542c4531..2ec82064fd2e 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1685,6 +1685,7 @@ static void xilinx_dpdma_chan_remove(struct xilinx_dpdma_chan *chan)
 		return;
 
 	tasklet_kill(&chan->err_task);
+	dma_chan_kill_bh(&chan->vchan.chan);
 	list_del(&chan->vchan.chan.device_node);
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (6 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 20/64] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
@ 2026-07-27 20:28   ` Allen Pais
  2026-07-27 20:36   ` [PATCH v2 33/64] dmaengine: sun6i: kill vchan BH on teardown Allen Pais
                     ` (10 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Michal Simek, Abin Joseph, Radhey Shyam Pandey, Sakari Ailus,
	linux-arm-kernel

Replace the per-channel tasklet with the shared dma_chan BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/zynqmp_dma.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index f6a812e49ddc..6291126cdc9f 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -207,7 +207,6 @@ struct zynqmp_dma_desc_sw {
  * @dev: The dma device
  * @irq: Channel IRQ
  * @is_dmacoherent: Tells whether dma operations are coherent or not
- * @tasklet: Cleanup work after irq
  * @idle : Channel status;
  * @desc_size: Size of the low level descriptor
  * @err: Channel has errors
@@ -232,7 +231,6 @@ struct zynqmp_dma_chan {
 	struct device *dev;
 	int irq;
 	bool is_dmacoherent;
-	struct tasklet_struct tasklet;
 	bool idle;
 	size_t desc_size;
 	bool err;
@@ -735,7 +733,7 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 	writel(isr, chan->regs + ZYNQMP_DMA_ISR);
 	if (status & ZYNQMP_DMA_INT_DONE) {
-		tasklet_schedule(&chan->tasklet);
+		dma_chan_schedule_bh(&chan->common);
 		ret = IRQ_HANDLED;
 	}
 
@@ -744,7 +742,7 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 	if (status & ZYNQMP_DMA_INT_ERR) {
 		chan->err = true;
-		tasklet_schedule(&chan->tasklet);
+		dma_chan_schedule_bh(&chan->common);
 		dev_err(chan->dev, "Channel %p has errors\n", chan);
 		ret = IRQ_HANDLED;
 	}
@@ -760,11 +758,12 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 /**
  * zynqmp_dma_do_tasklet - Schedule completion tasklet
- * @t: Pointer to the ZynqMP DMA channel structure
+ * @c: Pointer to the ZynqMP DMA channel structure
  */
-static void zynqmp_dma_do_tasklet(struct tasklet_struct *t)
+static void zynqmp_dma_do_tasklet(struct dma_chan *c)
 {
-	struct zynqmp_dma_chan *chan = from_tasklet(chan, t, tasklet);
+	struct zynqmp_dma_chan *chan = container_of(c,
+			struct zynqmp_dma_chan, common);
 	u32 count;
 	unsigned long irqflags;
 
@@ -815,7 +814,7 @@ static void zynqmp_dma_synchronize(struct dma_chan *dchan)
 {
 	struct zynqmp_dma_chan *chan = to_chan(dchan);
 
-	tasklet_kill(&chan->tasklet);
+	dma_chan_kill_bh(&chan->common);
 }
 
 /**
@@ -887,7 +886,7 @@ static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan)
 
 	if (chan->irq)
 		devm_free_irq(chan->zdev->dev, chan->irq, chan);
-	tasklet_kill(&chan->tasklet);
+	dma_chan_kill_bh(&chan->common);
 	list_del(&chan->common.device_node);
 }
 
@@ -937,7 +936,7 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
 
 	chan->is_dmacoherent =  of_property_read_bool(node, "dma-coherent");
 	zdev->chan = chan;
-	tasklet_setup(&chan->tasklet, zynqmp_dma_do_tasklet);
+	dma_chan_init_bh(&chan->common, zynqmp_dma_do_tasklet);
 	spin_lock_init(&chan->lock);
 	INIT_LIST_HEAD(&chan->active_list);
 	INIT_LIST_HEAD(&chan->pending_list);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 33/64] dmaengine: sun6i: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (7 preceding siblings ...)
  2026-07-27 20:28   ` [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH Allen Pais
@ 2026-07-27 20:36   ` Allen Pais
  2026-07-27 20:37   ` [PATCH v2 34/64] dmaengine: mtk-cqdma: " Allen Pais
                     ` (9 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:36 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, linux-arm-kernel,
	linux-sunxi

Use dma_chan_kill_bh() for virt-dma channel cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/sun6i-dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a9a254dbf8cb..9289c24dfcfa 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1097,7 +1097,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
 		struct sun6i_vchan *vchan = &sdev->vchans[i];
 
 		list_del(&vchan->vc.chan.device_node);
-		tasklet_kill(&vchan->vc.task);
+		dma_chan_kill_bh(&vchan->vc.chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 34/64] dmaengine: mtk-cqdma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (8 preceding siblings ...)
  2026-07-27 20:36   ` [PATCH v2 33/64] dmaengine: sun6i: kill vchan BH on teardown Allen Pais
@ 2026-07-27 20:37   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 43/64] dmaengine: pxa_dma: " Allen Pais
                     ` (8 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:37 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek

Use dma_chan_kill_bh() for virt-dma channel cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/mediatek/mtk-cqdma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c
index 80791e30aec2..3b0f1d8fa205 100644
--- a/drivers/dma/mediatek/mtk-cqdma.c
+++ b/drivers/dma/mediatek/mtk-cqdma.c
@@ -895,7 +895,7 @@ static void mtk_cqdma_remove(struct platform_device *pdev)
 		vc = &cqdma->vc[i];
 
 		list_del(&vc->vc.chan.device_node);
-		tasklet_kill(&vc->vc.task);
+		dma_chan_kill_bh(&vc->vc.chan);
 	}
 
 	/* disable interrupt */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 43/64] dmaengine: pxa_dma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (9 preceding siblings ...)
  2026-07-27 20:37   ` [PATCH v2 34/64] dmaengine: mtk-cqdma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 44/64] dmaengine: mtk-hsdma: " Allen Pais
                     ` (7 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Daniel Mack, Haojian Zhuang, Robert Jarzmik, linux-arm-kernel

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/pxa_dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index fa2ee0b3e09f..d57e5e0c422c 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -1215,7 +1215,7 @@ static void pxad_free_channels(struct dma_device *dmadev)
 	list_for_each_entry_safe(c, cn, &dmadev->channels,
 				 vc.chan.device_node) {
 		list_del(&c->vc.chan.device_node);
-		tasklet_kill(&c->vc.task);
+		dma_chan_kill_bh(&c->vc.chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 44/64] dmaengine: mtk-hsdma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (10 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 43/64] dmaengine: pxa_dma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 45/64] dmaengine: mtk-uart-apdma: " Allen Pais
                     ` (6 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/mediatek/mtk-hsdma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index a43412ff5edd..1c98fcedf3ac 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -1020,7 +1020,7 @@ static void mtk_hsdma_remove(struct platform_device *pdev)
 		vc = &hsdma->vc[i];
 
 		list_del(&vc->vc.chan.device_node);
-		tasklet_kill(&vc->vc.task);
+		dma_chan_kill_bh(&vc->vc.chan);
 	}
 
 	/* Disable DMA interrupt */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 45/64] dmaengine: mtk-uart-apdma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (11 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 44/64] dmaengine: mtk-hsdma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 46/64] dmaengine: imx-sdma: " Allen Pais
                     ` (5 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/mediatek/mtk-uart-apdma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
index c269d84d7bd2..4d89927922f5 100644
--- a/drivers/dma/mediatek/mtk-uart-apdma.c
+++ b/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -312,7 +312,7 @@ static void mtk_uart_apdma_free_chan_resources(struct dma_chan *chan)
 
 	free_irq(c->irq, chan);
 
-	tasklet_kill(&c->vc.task);
+	dma_chan_kill_bh(&c->vc.chan);
 
 	vchan_free_chan_resources(&c->vc);
 
@@ -463,7 +463,7 @@ static void mtk_uart_apdma_free(struct mtk_uart_apdmadev *mtkd)
 			struct mtk_chan, vc.chan.device_node);
 
 		list_del(&c->vc.chan.device_node);
-		tasklet_kill(&c->vc.task);
+		dma_chan_kill_bh(&c->vc.chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 46/64] dmaengine: imx-sdma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (12 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 45/64] dmaengine: mtk-uart-apdma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 48/64] dmaengine: owl-dma: " Allen Pais
                     ` (4 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, imx,
	linux-arm-kernel

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/imx-sdma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 36368835a845..46f66e5f9f30 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2399,11 +2399,11 @@ static void sdma_remove(struct platform_device *pdev)
 	int i;
 
 	devm_free_irq(&pdev->dev, sdma->irq, sdma);
-	/* Kill the tasklet */
+	/* Kill the channel BH */
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
 		struct sdma_channel *sdmac = &sdma->channel[i];
 
-		tasklet_kill(&sdmac->vc.task);
+		dma_chan_kill_bh(&sdmac->vc.chan);
 		sdma_free_chan_resources(&sdmac->vc.chan);
 	}
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 48/64] dmaengine: owl-dma: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (13 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 46/64] dmaengine: imx-sdma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 51/64] dmaengine: bcm2835: " Allen Pais
                     ` (3 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Andreas Färber, Manivannan Sadhasivam, linux-arm-kernel,
	linux-actions

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/owl-dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 7c80572fc71d..5f2140dc01ce 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -1055,7 +1055,7 @@ static inline void owl_dma_free(struct owl_dma *od)
 	list_for_each_entry_safe(vchan,
 				 next, &od->dma.channels, vc.chan.device_node) {
 		list_del(&vchan->vc.chan.device_node);
-		tasklet_kill(&vchan->vc.task);
+		dma_chan_kill_bh(&vchan->vc.chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 51/64] dmaengine: bcm2835: kill vchan BH on teardown
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (14 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 48/64] dmaengine: owl-dma: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh Allen Pais
                     ` (2 subsequent siblings)
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Florian Fainelli, Broadcom internal kernel review list, Ray Jui,
	Scott Branden, linux-rpi-kernel, linux-arm-kernel

Use dma_chan_kill_bh() for virt-dma cleanup.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/bcm2835-dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 06d830d36882..68e86c8d3d43 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -829,7 +829,7 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
 	list_for_each_entry_safe(c, next, &od->ddev.channels,
 				 vc.chan.device_node) {
 		list_del(&c->vc.chan.device_node);
-		tasklet_kill(&c->vc.task);
+		dma_chan_kill_bh(&c->vc.chan);
 	}
 
 	dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE,
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (15 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 51/64] dmaengine: bcm2835: " Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
  2026-07-27 20:39   ` [PATCH v2 62/64] dmaengine: hidma: defer callbacks via channel BH Allen Pais
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Patrice Chotard, linux-arm-kernel

virt-dma now dispatches completion callbacks through per-channel BH
work instead of its tasklet. Cancel that work during teardown before
channel storage is released.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/st_fdma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index d9547017f3bd..d4cff851e1d5 100644
--- a/drivers/dma/st_fdma.c
+++ b/drivers/dma/st_fdma.c
@@ -733,7 +733,7 @@ static void st_fdma_free(struct st_fdma_dev *fdev)
 	for (i = 0; i < fdev->nr_channels; i++) {
 		fchan = &fdev->chans[i];
 		list_del(&fchan->vchan.chan.device_node);
-		tasklet_kill(&fchan->vchan.task);
+		dma_chan_kill_bh(&fchan->vchan.chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 62/64] dmaengine: hidma: defer callbacks via channel BH
       [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
                     ` (16 preceding siblings ...)
  2026-07-27 20:39   ` [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh Allen Pais
@ 2026-07-27 20:39   ` Allen Pais
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
  18 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-07-27 20:39 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sinan Kaya, linux-arm-kernel, linux-arm-msm

Move descriptor callback processing out of the low-level completion
path and schedule it through per-channel BH work. Drain that work while
freeing channels so callbacks cannot outlive channel storage.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/qcom/hidma.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index c939635be21d..1f875a499ab3 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -90,7 +90,13 @@ static inline struct hidma_chan *to_hidma_chan(struct dma_chan *dmach)
 
 static void hidma_free(struct hidma_dev *dmadev)
 {
-	INIT_LIST_HEAD(&dmadev->ddev.channels);
+	struct hidma_chan *mchan, *next;
+
+	list_for_each_entry_safe(mchan, next, &dmadev->ddev.channels,
+				 chan.device_node) {
+		dma_chan_kill_bh(&mchan->chan);
+		list_del(&mchan->chan.device_node);
+	}
 }
 
 static unsigned int nr_desc_prm;
@@ -155,6 +161,13 @@ static void hidma_process_completed(struct hidma_chan *mchan)
 	}
 }
 
+static void hidma_chan_bh(struct dma_chan *chan)
+{
+	struct hidma_chan *mchan = to_hidma_chan(chan);
+
+	hidma_process_completed(mchan);
+}
+
 /*
  * Called once for each submitted descriptor.
  * PM is locked once for each descriptor that is currently
@@ -181,7 +194,7 @@ static void hidma_callback(void *data)
 	}
 	spin_unlock_irqrestore(&mchan->lock, irqflags);
 
-	hidma_process_completed(mchan);
+	dma_chan_schedule_bh(&mchan->chan);
 
 	if (queued) {
 		pm_runtime_mark_last_busy(dmadev->ddev.dev);
@@ -203,6 +216,7 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
 	mchan->dmadev = dmadev;
 	mchan->chan.device = ddev;
 	dma_cookie_init(&mchan->chan);
+	dma_chan_init_bh(&mchan->chan, hidma_chan_bh);
 
 	INIT_LIST_HEAD(&mchan->free);
 	INIT_LIST_HEAD(&mchan->prepared);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH
  2026-07-27 20:28   ` [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH Allen Pais
@ 2026-07-28 19:33     ` Linus Walleij
  0 siblings, 0 replies; 28+ messages in thread
From: Linus Walleij @ 2026-07-28 19:33 UTC (permalink / raw)
  To: Allen Pais
  Cc: Vinod Koul, Frank Li, dmaengine, linux-kernel, Arnd Bergmann,
	Kees Cook, linux-arm-kernel

On Mon, Jul 27, 2026 at 10:32 PM Allen Pais <allen.lkml@gmail.com> wrote:

> Replace the per-channel tasklet with the shared dma_chan BH helper.
> The handler continues to run in softirq context while dmaengine owns
> the common scheduling and teardown mechanism.
>
> Signed-off-by: Allen Pais <allen.lkml@gmail.com>

I like it.
Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 03/34] dmaengine: apple-admac: use dmaengine BH callback
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 04/34] dmaengine: at_xdmac: move irq bottom half to dmaengine BH Allen Pais
                       ` (7 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sven Peter, Janne Grunau, Neal Gompa, asahi, linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/apple-admac.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 14a5ee14a481..c5d4fb96d3c4 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -89,7 +89,6 @@ struct admac_chan {
 	unsigned int no;
 	struct admac_data *host;
 	struct dma_chan chan;
-	struct tasklet_struct tasklet;
 
 	u32 carveout;
 
@@ -521,10 +520,7 @@ static int admac_terminate_all(struct dma_chan *chan)
 		list_add_tail(&adchan->current_tx->node, &adchan->to_free);
 		adchan->current_tx = NULL;
 	}
-	/*
-	 * Descriptors can only be freed after the tasklet
-	 * has been killed (in admac_synchronize).
-	 */
+	/* Descriptors are released once the BH is flushed in admac_synchronize */
 	list_splice_tail_init(&adchan->submitted, &adchan->to_free);
 	list_splice_tail_init(&adchan->issued, &adchan->to_free);
 	spin_unlock_irqrestore(&adchan->lock, flags);
@@ -543,7 +539,7 @@ static void admac_synchronize(struct dma_chan *chan)
 	list_splice_tail_init(&adchan->to_free, &head);
 	spin_unlock_irqrestore(&adchan->lock, flags);
 
-	tasklet_kill(&adchan->tasklet);
+	dmaengine_kill_bh(&adchan->chan);
 
 	list_for_each_entry_safe(adtx, _adtx, &head, node) {
 		list_del(&adtx->node);
@@ -662,7 +658,7 @@ static void admac_handle_status_desc_done(struct admac_data *ad, int channo)
 		tx->reclaimed_pos %= 2 * tx->buf_len;
 
 		admac_cyclic_write_desc(ad, channo, tx);
-		tasklet_schedule(&adchan->tasklet);
+		dmaengine_schedule_bh(&adchan->chan);
 	}
 	spin_unlock_irqrestore(&adchan->lock, flags);
 }
@@ -712,9 +708,9 @@ static irqreturn_t admac_interrupt(int irq, void *devid)
 	return IRQ_HANDLED;
 }
 
-static void admac_chan_tasklet(struct tasklet_struct *t)
+static void admac_chan_bh(struct dma_chan *chan)
 {
-	struct admac_chan *adchan = from_tasklet(adchan, t, tasklet);
+	struct admac_chan *adchan = to_admac_chan(chan);
 	struct admac_tx *adtx;
 	struct dmaengine_desc_callback cb;
 	struct dmaengine_result tx_result;
@@ -886,7 +882,7 @@ static int admac_probe(struct platform_device *pdev)
 		INIT_LIST_HEAD(&adchan->issued);
 		INIT_LIST_HEAD(&adchan->to_free);
 		list_add_tail(&adchan->chan.device_node, &dma->channels);
-		tasklet_setup(&adchan->tasklet, admac_chan_tasklet);
+		dmaengine_init_bh(&adchan->chan, admac_chan_bh);
 	}
 
 	err = reset_control_reset(ad->rstc);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 04/34] dmaengine: at_xdmac: move irq bottom half to dmaengine BH
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
  2026-08-10 18:09     ` [PATCH v3 03/34] dmaengine: apple-admac: use dmaengine BH callback Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 08/34] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
                       ` (6 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Ludovic Desroches, linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/at_xdmac.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 901971e8bae6..5a970f9f3831 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -228,7 +228,6 @@ struct at_xdmac_chan {
 	u32				save_cndc;
 	u32				irq_status;
 	unsigned long			status;
-	struct tasklet_struct		tasklet;
 	struct dma_slave_config		sconfig;
 
 	spinlock_t			lock;
@@ -1759,9 +1758,9 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)
 	/* Then continue with usual descriptor management */
 }
 
-static void at_xdmac_tasklet(struct tasklet_struct *t)
+static void at_xdmac_tasklet(struct dma_chan *chan)
 {
-	struct at_xdmac_chan	*atchan = from_tasklet(atchan, t, tasklet);
+	struct at_xdmac_chan	*atchan = to_at_xdmac_chan(chan);
 	struct at_xdmac		*atxdmac = to_at_xdmac(atchan->chan.device);
 	struct at_xdmac_desc	*desc;
 	struct dma_async_tx_descriptor *txd;
@@ -1865,7 +1864,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
 			if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
 				at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
 
-			tasklet_schedule(&atchan->tasklet);
+			dmaengine_schedule_bh(&atchan->chan);
 			ret = IRQ_HANDLED;
 		}
 
@@ -2317,7 +2316,7 @@ static int at_xdmac_probe(struct platform_device *pdev)
 		return PTR_ERR(atxdmac->clk);
 	}
 
-	/* Do not use dev res to prevent races with tasklet */
+	/* Do not use devm resources to prevent races with the BH worker */
 	ret = request_irq(atxdmac->irq, at_xdmac_interrupt, 0, "at_xdmac", atxdmac);
 	if (ret) {
 		dev_err(&pdev->dev, "can't request irq\n");
@@ -2397,7 +2396,7 @@ static int at_xdmac_probe(struct platform_device *pdev)
 		spin_lock_init(&atchan->lock);
 		INIT_LIST_HEAD(&atchan->xfers_list);
 		INIT_LIST_HEAD(&atchan->free_descs_list);
-		tasklet_setup(&atchan->tasklet, at_xdmac_tasklet);
+		dmaengine_init_bh(&atchan->chan, at_xdmac_tasklet);
 
 		/* Clear pending interrupts. */
 		while (at_xdmac_chan_read(atchan, AT_XDMAC_CIS))
@@ -2458,7 +2457,7 @@ static void at_xdmac_remove(struct platform_device *pdev)
 	for (i = 0; i < atxdmac->dma.chancnt; i++) {
 		struct at_xdmac_chan *atchan = &atxdmac->chan[i];
 
-		tasklet_kill(&atchan->tasklet);
+		dmaengine_kill_bh(&atchan->chan);
 		at_xdmac_free_chan_resources(&atchan->chan);
 	}
 }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 08/34] dmaengine: imx-dma: flip per-chan tasklet to dmaengine BH
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
  2026-08-10 18:09     ` [PATCH v3 03/34] dmaengine: apple-admac: use dmaengine BH callback Allen Pais
  2026-08-10 18:09     ` [PATCH v3 04/34] dmaengine: at_xdmac: move irq bottom half to dmaengine BH Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 13/34] dmaengine: mxs-dma: use dmaengine BH scheduling Allen Pais
                       ` (5 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, imx,
	linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/imx-dma.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 81c6276436f8..308fe407fe16 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -145,7 +145,6 @@ struct imxdma_channel {
 	struct imxdma_engine		*imxdma;
 	unsigned int			channel;
 
-	struct tasklet_struct		dma_tasklet;
 	struct list_head		ld_free;
 	struct list_head		ld_queue;
 	struct list_head		ld_active;
@@ -344,8 +343,8 @@ static void imxdma_watchdog(struct timer_list *t)
 
 	imx_dmav1_writel(imxdma, 0, DMA_CCR(channel));
 
-	/* Tasklet watchdog error handler */
-	tasklet_schedule(&imxdmac->dma_tasklet);
+	/* BH watchdog error handler */
+	dmaengine_schedule_bh(&imxdmac->chan);
 	dev_dbg(imxdma->dev, "channel %d: watchdog timeout!\n",
 		imxdmac->channel);
 }
@@ -390,8 +389,8 @@ static irqreturn_t imxdma_err_handler(int irq, void *dev_id)
 			imx_dmav1_writel(imxdma, 1 << i, DMA_DBOSR);
 			errcode |= IMX_DMA_ERR_BUFFER;
 		}
-		/* Tasklet error handler */
-		tasklet_schedule(&imxdma->channel[i].dma_tasklet);
+		/* BH error handler */
+		dmaengine_schedule_bh(&imxdma->channel[i].chan);
 
 		dev_warn(imxdma->dev,
 			 "DMA timeout on channel %d -%s%s%s%s\n", i,
@@ -448,8 +447,8 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
 			imx_dmav1_writel(imxdma, tmp, DMA_CCR(chno));
 
 			if (imxdma_chan_is_doing_cyclic(imxdmac))
-				/* Tasklet progression */
-				tasklet_schedule(&imxdmac->dma_tasklet);
+				/* BH progression */
+				dmaengine_schedule_bh(&imxdmac->chan);
 
 			return;
 		}
@@ -462,8 +461,8 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
 
 out:
 	imx_dmav1_writel(imxdma, 0, DMA_CCR(chno));
-	/* Tasklet irq */
-	tasklet_schedule(&imxdmac->dma_tasklet);
+	/* Schedule the IRQ BH */
+	dmaengine_schedule_bh(&imxdmac->chan);
 }
 
 static irqreturn_t dma_irq_handler(int irq, void *dev_id)
@@ -592,9 +591,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
 	return 0;
 }
 
-static void imxdma_tasklet(struct tasklet_struct *t)
+static void imxdma_tasklet(struct dma_chan *chan)
 {
-	struct imxdma_channel *imxdmac = from_tasklet(imxdmac, t, dma_tasklet);
+	struct imxdma_channel *imxdmac = container_of(chan, struct imxdma_channel,
+						      chan);
 	struct imxdma_engine *imxdma = imxdmac->imxdma;
 	struct imxdma_desc *desc, *next_desc;
 	unsigned long flags;
@@ -1142,7 +1142,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
 		INIT_LIST_HEAD(&imxdmac->ld_free);
 		INIT_LIST_HEAD(&imxdmac->ld_active);
 
-		tasklet_setup(&imxdmac->dma_tasklet, imxdma_tasklet);
+		dmaengine_init_bh(&imxdmac->chan, imxdma_tasklet);
 		imxdmac->chan.device = &imxdma->dma_device;
 		dma_cookie_init(&imxdmac->chan);
 		imxdmac->channel = i;
@@ -1211,7 +1211,7 @@ static void imxdma_free_irq(struct platform_device *pdev, struct imxdma_engine *
 		if (!is_imx1_dma(imxdma))
 			disable_irq(imxdmac->irq);
 
-		tasklet_kill(&imxdmac->dma_tasklet);
+		dmaengine_kill_bh(&imxdmac->chan);
 	}
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 13/34] dmaengine: mxs-dma: use dmaengine BH scheduling
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (2 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 08/34] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 17/34] dmaengine: ste_dma40: convert per-channel tasklet to dmaengine BH Allen Pais
                       ` (4 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, imx,
	linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/mxs-dma.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 7acb3d29dad3..149ac402f7b4 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -109,7 +109,6 @@ struct mxs_dma_chan {
 	struct mxs_dma_engine		*mxs_dma;
 	struct dma_chan			chan;
 	struct dma_async_tx_descriptor	desc;
-	struct tasklet_struct		tasklet;
 	unsigned int			chan_irq;
 	struct mxs_dma_ccw		*ccw;
 	dma_addr_t			ccw_phys;
@@ -300,9 +299,9 @@ static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	return dma_cookie_assign(tx);
 }
 
-static void mxs_dma_tasklet(struct tasklet_struct *t)
+static void mxs_dma_tasklet(struct dma_chan *chan)
 {
-	struct mxs_dma_chan *mxs_chan = from_tasklet(mxs_chan, t, tasklet);
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
 
 	dmaengine_desc_get_callback_invoke(&mxs_chan->desc, NULL);
 }
@@ -386,8 +385,8 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
 		dma_cookie_complete(&mxs_chan->desc);
 	}
 
-	/* schedule tasklet on this channel */
-	tasklet_schedule(&mxs_chan->tasklet);
+	/* schedule BH on this channel */
+	dmaengine_schedule_bh(&mxs_chan->chan);
 
 	return IRQ_HANDLED;
 }
@@ -781,7 +780,7 @@ static int mxs_dma_probe(struct platform_device *pdev)
 		mxs_chan->chan.device = &mxs_dma->dma_device;
 		dma_cookie_init(&mxs_chan->chan);
 
-		tasklet_setup(&mxs_chan->tasklet, mxs_dma_tasklet);
+		dmaengine_init_bh(&mxs_chan->chan, mxs_dma_tasklet);
 
 
 		/* Add the channel to mxs_chan list */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 17/34] dmaengine: ste_dma40: convert per-channel tasklet to dmaengine BH
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (3 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 13/34] dmaengine: mxs-dma: use dmaengine BH scheduling Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 19/34] dmaengine: xilinx-dma: use dmaengine BH instead of tasklets Allen Pais
                       ` (3 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Linus Walleij, linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
---
 drivers/dma/ste_dma40.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 0d9ffa3e2663..e6dfa1fc5e5a 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -461,8 +461,6 @@ struct d40_base;
  * @phy_chan: Pointer to physical channel which this instance runs on. If this
  * point is NULL, then the channel is not allocated.
  * @chan: DMA engine handle.
- * @tasklet: Tasklet that gets scheduled from interrupt context to complete a
- * transfer and call client callback.
  * @client: Cliented owned descriptor list.
  * @pending_queue: Submitted jobs, to be issued by issue_pending()
  * @active: Active descriptor.
@@ -489,7 +487,6 @@ struct d40_chan {
 	bool				 busy;
 	struct d40_phy_res		*phy_chan;
 	struct dma_chan			 chan;
-	struct tasklet_struct		 tasklet;
 	struct list_head		 client;
 	struct list_head		 pending_queue;
 	struct list_head		 active;
@@ -1587,13 +1584,13 @@ static void dma_tc_handle(struct d40_chan *d40c)
 	}
 
 	d40c->pending_tx++;
-	tasklet_schedule(&d40c->tasklet);
+	dmaengine_schedule_bh(&d40c->chan);
 
 }
 
-static void dma_tasklet(struct tasklet_struct *t)
+static void dma_tasklet(struct dma_chan *chan)
 {
-	struct d40_chan *d40c = from_tasklet(d40c, t, tasklet);
+	struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
 	struct d40_desc *d40d;
 	unsigned long flags;
 	bool callback_active;
@@ -1641,7 +1638,7 @@ static void dma_tasklet(struct tasklet_struct *t)
 	d40c->pending_tx--;
 
 	if (d40c->pending_tx)
-		tasklet_schedule(&d40c->tasklet);
+		dmaengine_schedule_bh(&d40c->chan);
 
 	spin_unlock_irqrestore(&d40c->lock, flags);
 
@@ -2815,7 +2812,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
 		INIT_LIST_HEAD(&d40c->client);
 		INIT_LIST_HEAD(&d40c->prepare_queue);
 
-		tasklet_setup(&d40c->tasklet, dma_tasklet);
+		dmaengine_init_bh(&d40c->chan, dma_tasklet);
 
 		list_add_tail(&d40c->chan.device_node,
 			      &dma->channels);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 19/34] dmaengine: xilinx-dma: use dmaengine BH instead of tasklets
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (4 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 17/34] dmaengine: ste_dma40: convert per-channel tasklet to dmaengine BH Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 20/34] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
                       ` (2 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Michal Simek, Suraj Gupta, Marek Vasut, Folker Schwesinger,
	Tomi Valkeinen, Krzysztof Kozlowski, linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/xilinx_dma.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 404235c17353..b142c9c0583c 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -402,7 +402,6 @@ struct xilinx_dma_tx_descriptor {
  * @err: Channel has errors
  * @idle: Check for channel idle
  * @terminating: Check for channel being synchronized by user
- * @tasklet: Cleanup work after irq
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
  * @desc_pendingcount: Descriptor pending count
@@ -441,7 +440,6 @@ struct xilinx_dma_chan {
 	bool err;
 	bool idle;
 	bool terminating;
-	struct tasklet_struct tasklet;
 	struct xilinx_vdma_config config;
 	bool flush_on_fsync;
 	u32 desc_pendingcount;
@@ -1115,11 +1113,12 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
 
 /**
  * xilinx_dma_do_tasklet - Schedule completion tasklet
- * @t: Pointer to the Xilinx DMA channel structure
+ * @c: Pointer to the Xilinx DMA channel structure
  */
-static void xilinx_dma_do_tasklet(struct tasklet_struct *t)
+static void xilinx_dma_do_tasklet(struct dma_chan *c)
 {
-	struct xilinx_dma_chan *chan = from_tasklet(chan, t, tasklet);
+	struct xilinx_dma_chan *chan = container_of(c,
+			struct xilinx_dma_chan, common);
 
 	xilinx_dma_chan_desc_cleanup(chan);
 }
@@ -1898,7 +1897,7 @@ static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data)
 		spin_unlock(&chan->lock);
 	}
 
-	tasklet_hi_schedule(&chan->tasklet);
+	dmaengine_schedule_bh(&chan->common);
 	return IRQ_HANDLED;
 }
 
@@ -1955,7 +1954,7 @@ static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
 		spin_unlock(&chan->lock);
 	}
 
-	tasklet_schedule(&chan->tasklet);
+	dmaengine_schedule_bh(&chan->common);
 	return IRQ_HANDLED;
 }
 
@@ -2654,7 +2653,7 @@ static void xilinx_dma_synchronize(struct dma_chan *dchan)
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 
-	tasklet_kill(&chan->tasklet);
+	dmaengine_kill_bh(&chan->common);
 }
 
 /**
@@ -2745,7 +2744,7 @@ static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
 	if (chan->irq > 0)
 		free_irq(chan->irq, chan);
 
-	tasklet_kill(&chan->tasklet);
+	dmaengine_kill_bh(&chan->common);
 
 	list_del(&chan->common.device_node);
 }
@@ -3075,8 +3074,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 			str_enabled_disabled(chan->has_sg));
 	}
 
-	/* Initialize the tasklet */
-	tasklet_setup(&chan->tasklet, xilinx_dma_do_tasklet);
+	dmaengine_init_bh(&chan->common, xilinx_dma_do_tasklet);
 
 	/*
 	 * Initialize the DMA channel and add it to the DMA engine channels
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 20/34] dmaengine: xilinx-dpdma: kill vchan BH on remove
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (5 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 19/34] dmaengine: xilinx-dma: use dmaengine BH instead of tasklets Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 21/34] dmaengine: zynqmp-dma: switch completion tasklet to dmaengine BH Allen Pais
  2026-08-10 18:09     ` [PATCH v3 32/34] dmaengine: hidma: defer callbacks via channel BH Allen Pais
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Laurent Pinchart, Michal Simek, linux-arm-kernel

virt-dma now dispatches completion callbacks through per-channel BH
work. Cancel that work when removing a channel, while retaining the
driver's separate error-handling tasklet.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/xilinx_dpdma.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index d9a3542c4531..7e147ea11368 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1685,6 +1685,7 @@ static void xilinx_dpdma_chan_remove(struct xilinx_dpdma_chan *chan)
 		return;
 
 	tasklet_kill(&chan->err_task);
+	dmaengine_kill_bh(&chan->vchan.chan);
 	list_del(&chan->vchan.chan.device_node);
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 21/34] dmaengine: zynqmp-dma: switch completion tasklet to dmaengine BH
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (6 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 20/34] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  2026-08-10 18:09     ` [PATCH v3 32/34] dmaengine: hidma: defer callbacks via channel BH Allen Pais
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Michal Simek, Abin Joseph, Sakari Ailus, linux-arm-kernel

Replace the per-channel tasklet with the shared dmaengine BH helper.
The handler continues to run in softirq context while dmaengine owns
the common scheduling and teardown mechanism.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/xilinx/zynqmp_dma.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index f6a812e49ddc..e396a35f0e0d 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -207,7 +207,6 @@ struct zynqmp_dma_desc_sw {
  * @dev: The dma device
  * @irq: Channel IRQ
  * @is_dmacoherent: Tells whether dma operations are coherent or not
- * @tasklet: Cleanup work after irq
  * @idle : Channel status;
  * @desc_size: Size of the low level descriptor
  * @err: Channel has errors
@@ -232,7 +231,6 @@ struct zynqmp_dma_chan {
 	struct device *dev;
 	int irq;
 	bool is_dmacoherent;
-	struct tasklet_struct tasklet;
 	bool idle;
 	size_t desc_size;
 	bool err;
@@ -735,7 +733,7 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 	writel(isr, chan->regs + ZYNQMP_DMA_ISR);
 	if (status & ZYNQMP_DMA_INT_DONE) {
-		tasklet_schedule(&chan->tasklet);
+		dmaengine_schedule_bh(&chan->common);
 		ret = IRQ_HANDLED;
 	}
 
@@ -744,7 +742,7 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 	if (status & ZYNQMP_DMA_INT_ERR) {
 		chan->err = true;
-		tasklet_schedule(&chan->tasklet);
+		dmaengine_schedule_bh(&chan->common);
 		dev_err(chan->dev, "Channel %p has errors\n", chan);
 		ret = IRQ_HANDLED;
 	}
@@ -760,11 +758,12 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
 
 /**
  * zynqmp_dma_do_tasklet - Schedule completion tasklet
- * @t: Pointer to the ZynqMP DMA channel structure
+ * @c: Pointer to the ZynqMP DMA channel structure
  */
-static void zynqmp_dma_do_tasklet(struct tasklet_struct *t)
+static void zynqmp_dma_do_tasklet(struct dma_chan *c)
 {
-	struct zynqmp_dma_chan *chan = from_tasklet(chan, t, tasklet);
+	struct zynqmp_dma_chan *chan = container_of(c,
+			struct zynqmp_dma_chan, common);
 	u32 count;
 	unsigned long irqflags;
 
@@ -815,7 +814,7 @@ static void zynqmp_dma_synchronize(struct dma_chan *dchan)
 {
 	struct zynqmp_dma_chan *chan = to_chan(dchan);
 
-	tasklet_kill(&chan->tasklet);
+	dmaengine_kill_bh(&chan->common);
 }
 
 /**
@@ -887,7 +886,7 @@ static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan)
 
 	if (chan->irq)
 		devm_free_irq(chan->zdev->dev, chan->irq, chan);
-	tasklet_kill(&chan->tasklet);
+	dmaengine_kill_bh(&chan->common);
 	list_del(&chan->common.device_node);
 }
 
@@ -937,7 +936,7 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
 
 	chan->is_dmacoherent =  of_property_read_bool(node, "dma-coherent");
 	zdev->chan = chan;
-	tasklet_setup(&chan->tasklet, zynqmp_dma_do_tasklet);
+	dmaengine_init_bh(&chan->common, zynqmp_dma_do_tasklet);
 	spin_lock_init(&chan->lock);
 	INIT_LIST_HEAD(&chan->active_list);
 	INIT_LIST_HEAD(&chan->pending_list);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 32/34] dmaengine: hidma: defer callbacks via channel BH
       [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
                       ` (7 preceding siblings ...)
  2026-08-10 18:09     ` [PATCH v3 21/34] dmaengine: zynqmp-dma: switch completion tasklet to dmaengine BH Allen Pais
@ 2026-08-10 18:09     ` Allen Pais
  8 siblings, 0 replies; 28+ messages in thread
From: Allen Pais @ 2026-08-10 18:09 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: Allen Pais, dmaengine, linux-kernel, Arnd Bergmann, Kees Cook,
	Sinan Kaya, linux-arm-kernel, linux-arm-msm

Move descriptor callback processing out of the low-level completion
path and schedule it through per-channel BH work. Drain that work while
freeing channels so callbacks cannot outlive channel storage.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/dma/qcom/hidma.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index c939635be21d..486a2c61a9fb 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -90,7 +90,13 @@ static inline struct hidma_chan *to_hidma_chan(struct dma_chan *dmach)
 
 static void hidma_free(struct hidma_dev *dmadev)
 {
-	INIT_LIST_HEAD(&dmadev->ddev.channels);
+	struct hidma_chan *mchan, *next;
+
+	list_for_each_entry_safe(mchan, next, &dmadev->ddev.channels,
+				 chan.device_node) {
+		dmaengine_kill_bh(&mchan->chan);
+		list_del(&mchan->chan.device_node);
+	}
 }
 
 static unsigned int nr_desc_prm;
@@ -155,6 +161,13 @@ static void hidma_process_completed(struct hidma_chan *mchan)
 	}
 }
 
+static void hidma_chan_bh(struct dma_chan *chan)
+{
+	struct hidma_chan *mchan = to_hidma_chan(chan);
+
+	hidma_process_completed(mchan);
+}
+
 /*
  * Called once for each submitted descriptor.
  * PM is locked once for each descriptor that is currently
@@ -181,7 +194,7 @@ static void hidma_callback(void *data)
 	}
 	spin_unlock_irqrestore(&mchan->lock, irqflags);
 
-	hidma_process_completed(mchan);
+	dmaengine_schedule_bh(&mchan->chan);
 
 	if (queued) {
 		pm_runtime_mark_last_busy(dmadev->ddev.dev);
@@ -203,6 +216,7 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
 	mchan->dmadev = dmadev;
 	mchan->chan.device = ddev;
 	dma_cookie_init(&mchan->chan);
+	dmaengine_init_bh(&mchan->chan, hidma_chan_bh);
 
 	INIT_LIST_HEAD(&mchan->free);
 	INIT_LIST_HEAD(&mchan->prepared);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2026-08-10 18:13 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260108080332.2341725-1-allen.lkml@gmail.com>
     [not found] ` <cover.1785183549.git.allen.lkml@gmail.com>
2026-07-27 20:28   ` [PATCH v2 03/64] dmaengine: apple-admac: use dma_chan BH callback Allen Pais
2026-07-27 20:28   ` [PATCH v2 04/64] dmaengine: at_xdmac: move irq bottom half to dma_chan BH Allen Pais
2026-07-27 20:28   ` [PATCH v2 08/64] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
2026-07-27 20:28   ` [PATCH v2 13/64] dmaengine: mxs-dma: use dma_chan BH scheduling Allen Pais
2026-07-27 20:28   ` [PATCH v2 17/64] dmaengine: ste_dma40: convert per-channel tasklet to dma_chan BH Allen Pais
2026-07-28 19:33     ` Linus Walleij
2026-07-27 20:28   ` [PATCH v2 19/64] dmaengine: xilinx-dma: use dma_chan BH instead of tasklets Allen Pais
2026-07-27 20:28   ` [PATCH v2 20/64] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
2026-07-27 20:28   ` [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH Allen Pais
2026-07-27 20:36   ` [PATCH v2 33/64] dmaengine: sun6i: kill vchan BH on teardown Allen Pais
2026-07-27 20:37   ` [PATCH v2 34/64] dmaengine: mtk-cqdma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 43/64] dmaengine: pxa_dma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 44/64] dmaengine: mtk-hsdma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 45/64] dmaengine: mtk-uart-apdma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 46/64] dmaengine: imx-sdma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 48/64] dmaengine: owl-dma: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 51/64] dmaengine: bcm2835: " Allen Pais
2026-07-27 20:39   ` [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh Allen Pais
2026-07-27 20:39   ` [PATCH v2 62/64] dmaengine: hidma: defer callbacks via channel BH Allen Pais
     [not found]   ` <cover.1786384168.git.allen.lkml@gmail.com>
2026-08-10 18:09     ` [PATCH v3 03/34] dmaengine: apple-admac: use dmaengine BH callback Allen Pais
2026-08-10 18:09     ` [PATCH v3 04/34] dmaengine: at_xdmac: move irq bottom half to dmaengine BH Allen Pais
2026-08-10 18:09     ` [PATCH v3 08/34] dmaengine: imx-dma: flip per-chan tasklet " Allen Pais
2026-08-10 18:09     ` [PATCH v3 13/34] dmaengine: mxs-dma: use dmaengine BH scheduling Allen Pais
2026-08-10 18:09     ` [PATCH v3 17/34] dmaengine: ste_dma40: convert per-channel tasklet to dmaengine BH Allen Pais
2026-08-10 18:09     ` [PATCH v3 19/34] dmaengine: xilinx-dma: use dmaengine BH instead of tasklets Allen Pais
2026-08-10 18:09     ` [PATCH v3 20/34] dmaengine: xilinx-dpdma: kill vchan BH on remove Allen Pais
2026-08-10 18:09     ` [PATCH v3 21/34] dmaengine: zynqmp-dma: switch completion tasklet to dmaengine BH Allen Pais
2026-08-10 18:09     ` [PATCH v3 32/34] dmaengine: hidma: defer callbacks via channel BH Allen Pais

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox