Re: [PATCH v12 02/12] dmaengine: qcom: bam_dma: convert tasklet to a BH workqueue
From: Manivannan Sadhasivam
Date: Wed Mar 11 2026 - 08:48:49 EST
On Tue, Mar 10, 2026 at 04:44:16PM +0100, Bartosz Golaszewski wrote:
> BH workqueues are a modern mechanism, aiming to replace legacy tasklets.
> Let's convert the BAM DMA driver to using the high-priority variant of
> the BH workqueue.
>
> [Vinod: suggested using the BG workqueue instead of the regular one
> running in process context]
>
> Suggested-by: Vinod Koul <vkoul@xxxxxxxxxx>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
> Reviewed-by: Bjorn Andersson <andersson@xxxxxxxxxx>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
Reviewed-by: Manivannan Sadhasivam <mani@xxxxxxxxxx>
- Mani
> ---
> drivers/dma/qcom/bam_dma.c | 32 ++++++++++++++++----------------
> 1 file changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
> index 19116295f8325767a0d97a7848077885b118241c..c8601bac555edf1bb4384fd39cb3449ec6e86334 100644
> --- a/drivers/dma/qcom/bam_dma.c
> +++ b/drivers/dma/qcom/bam_dma.c
> @@ -42,6 +42,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> +#include <linux/workqueue.h>
>
> #include "../dmaengine.h"
> #include "../virt-dma.h"
> @@ -397,8 +398,8 @@ struct bam_device {
> struct clk *bamclk;
> int irq;
>
> - /* dma start transaction tasklet */
> - struct tasklet_struct task;
> + /* dma start transaction workqueue */
> + struct work_struct work;
> };
>
> /**
> @@ -863,7 +864,7 @@ static u32 process_channel_irqs(struct bam_device *bdev)
> /*
> * if complete, process cookie. Otherwise
> * push back to front of desc_issued so that
> - * it gets restarted by the tasklet
> + * it gets restarted by the work queue.
> */
> if (!async_desc->num_desc) {
> vchan_cookie_complete(&async_desc->vd);
> @@ -893,9 +894,9 @@ static irqreturn_t bam_dma_irq(int irq, void *data)
>
> srcs |= process_channel_irqs(bdev);
>
> - /* kick off tasklet to start next dma transfer */
> + /* kick off the work queue to start next dma transfer */
> if (srcs & P_IRQ)
> - tasklet_schedule(&bdev->task);
> + queue_work(system_bh_highpri_wq, &bdev->work);
>
> ret = pm_runtime_get_sync(bdev->dev);
> if (ret < 0)
> @@ -1091,14 +1092,14 @@ static void bam_start_dma(struct bam_chan *bchan)
> }
>
> /**
> - * dma_tasklet - DMA IRQ tasklet
> - * @t: tasklet argument (bam controller structure)
> + * bam_dma_work() - DMA interrupt work queue callback
> + * @work: work queue struct embedded in the BAM controller device struct
> *
> * Sets up next DMA operation and then processes all completed transactions
> */
> -static void dma_tasklet(struct tasklet_struct *t)
> +static void bam_dma_work(struct work_struct *work)
> {
> - struct bam_device *bdev = from_tasklet(bdev, t, task);
> + struct bam_device *bdev = from_work(bdev, work, work);
> struct bam_chan *bchan;
> unsigned int i;
>
> @@ -1111,14 +1112,13 @@ static void dma_tasklet(struct tasklet_struct *t)
> if (!list_empty(&bchan->vc.desc_issued) && !IS_BUSY(bchan))
> bam_start_dma(bchan);
> }
> -
> }
>
> /**
> * bam_issue_pending - starts pending transactions
> * @chan: dma channel
> *
> - * Calls tasklet directly which in turn starts any pending transactions
> + * Calls work queue directly which in turn starts any pending transactions
> */
> static void bam_issue_pending(struct dma_chan *chan)
> {
> @@ -1286,14 +1286,14 @@ static int bam_dma_probe(struct platform_device *pdev)
> if (ret)
> goto err_disable_clk;
>
> - tasklet_setup(&bdev->task, dma_tasklet);
> + INIT_WORK(&bdev->work, bam_dma_work);
>
> bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels,
> sizeof(*bdev->channels), GFP_KERNEL);
>
> if (!bdev->channels) {
> ret = -ENOMEM;
> - goto err_tasklet_kill;
> + goto err_workqueue_cancel;
> }
>
> /* allocate and initialize channels */
> @@ -1358,8 +1358,8 @@ static int bam_dma_probe(struct platform_device *pdev)
> err_bam_channel_exit:
> for (i = 0; i < bdev->num_channels; i++)
> tasklet_kill(&bdev->channels[i].vc.task);
> -err_tasklet_kill:
> - tasklet_kill(&bdev->task);
> +err_workqueue_cancel:
> + cancel_work_sync(&bdev->work);
> err_disable_clk:
> clk_disable_unprepare(bdev->bamclk);
>
> @@ -1393,7 +1393,7 @@ static void bam_dma_remove(struct platform_device *pdev)
> bdev->channels[i].fifo_phys);
> }
>
> - tasklet_kill(&bdev->task);
> + cancel_work_sync(&bdev->work);
>
> clk_disable_unprepare(bdev->bamclk);
> }
>
> --
> 2.47.3
>
--
மணிவண்ணன் சதாசிவம்