[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aYYm2pA6l-ksXvkk@lizhi-Precision-Tower-5810>
Date: Fri, 6 Feb 2026 12:37:30 -0500
From: Frank Li <Frank.li@....com>
To: Pat Somaru <patso@...ewhatevs.io>
Cc: Tejun Heo <tj@...nel.org>, Logan Gunthorpe <logang@...tatee.com>,
Vinod Koul <vkoul@...nel.org>, dmaengine@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] dma: plx_dma: Convert from tasklet to BH workqueue
On Fri, Feb 06, 2026 at 04:00:58AM -0500, Pat Somaru wrote:
> The only generic interface to execute asynchronously in the BH context
> is tasklet; however, it's marked deprecated and has some design flaws
> such as the execution code accessing the tasklet item after the
> execution is complete which can lead to subtle use-after-free in certain
> usage scenarios and less-developed flush and cancel mechanisms.
>
> To replace tasklets, BH workqueue support was recently added. A BH
> workqueue behaves similarly to regular workqueues except that the queued
> work items are executed in the BH context.
>
> This patch converts drivers/dma/plx_dma.c from tasklet to BH workqueue.
>
> The PLX DMA driver uses a single tasklet to process completed DMA
> descriptors in BH context after an interrupt signals descriptor
> completion. This conversion maintains the same execution semantics while
> using the modern BH workqueue infrastructure.
>
> This patch was tested by:
> - Building with allmodconfig: no new warnings (compared to v6.18)
> - Building with allyesconfig: no new warnings (compared to v6.18)
> - Booting defconfig kernel via vng and running `uname -a`:
> Linux virtme-ng 6.18.0-virtme #1 SMP PREEMPT_DYNAMIC 0 x86_64 GNU/Linux
>
> Semantically, this is an equivalent conversion and there shouldn't be
> any user-visible behavior changes. The BH workqueue implementation uses
> the same softirq infrastructure, and performance-critical networking
> conversions have shown no measurable performance impact.
>
> Maintainers can apply this directly to the DMA subsystem tree or ack it
> for the workqueue tree to carry.
>
> Signed-off-by: Pat Somaru <patso@...ewhatevs.io>
> ---
Reviewed-by: Frank Li <Frank.Li@....com>
> drivers/dma/plx_dma.c | 13 +++++++------
> 1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
> index 34b6416c3287..be13a7fa5763 100644
> --- a/drivers/dma/plx_dma.c
> +++ b/drivers/dma/plx_dma.c
> @@ -13,6 +13,7 @@
> #include <linux/list.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> +#include <linux/workqueue.h>
>
> MODULE_DESCRIPTION("PLX ExpressLane PEX PCI Switch DMA Engine");
> MODULE_VERSION("0.1");
> @@ -105,7 +106,7 @@ struct plx_dma_dev {
> struct dma_chan dma_chan;
> struct pci_dev __rcu *pdev;
> void __iomem *bar;
> - struct tasklet_struct desc_task;
> + struct work_struct desc_task;
>
> spinlock_t ring_lock;
> bool ring_active;
> @@ -241,9 +242,9 @@ static void plx_dma_stop(struct plx_dma_dev *plxdev)
> rcu_read_unlock();
> }
>
> -static void plx_dma_desc_task(struct tasklet_struct *t)
> +static void plx_dma_desc_task(struct work_struct *work)
> {
> - struct plx_dma_dev *plxdev = from_tasklet(plxdev, t, desc_task);
> + struct plx_dma_dev *plxdev = from_work(plxdev, work, desc_task);
>
> plx_dma_process_desc(plxdev);
> }
> @@ -366,7 +367,7 @@ static irqreturn_t plx_dma_isr(int irq, void *devid)
> return IRQ_NONE;
>
> if (status & PLX_REG_INTR_STATUS_DESC_DONE && plxdev->ring_active)
> - tasklet_schedule(&plxdev->desc_task);
> + queue_work(system_bh_wq, &plxdev->desc_task);
>
> writew(status, plxdev->bar + PLX_REG_INTR_STATUS);
>
> @@ -472,7 +473,7 @@ static void plx_dma_free_chan_resources(struct dma_chan *chan)
> if (irq > 0)
> synchronize_irq(irq);
>
> - tasklet_kill(&plxdev->desc_task);
> + cancel_work_sync(&plxdev->desc_task);
>
> plx_dma_abort_desc(plxdev);
>
> @@ -511,7 +512,7 @@ static int plx_dma_create(struct pci_dev *pdev)
> goto free_plx;
>
> spin_lock_init(&plxdev->ring_lock);
> - tasklet_setup(&plxdev->desc_task, plx_dma_desc_task);
> + INIT_WORK(&plxdev->desc_task, plx_dma_desc_task);
>
> RCU_INIT_POINTER(plxdev->pdev, pdev);
> plxdev->bar = pcim_iomap_table(pdev)[0];
> --
> 2.52.0
>
Powered by blists - more mailing lists