Re: [PATCH v2 06/64] dmaengine: fsldma: migrate tasklet to dma_chan BH

[email protected] Mon, 27 Jul 2026 20:56:19 +0000
Newsgroups org.kernel.vger.dmaengine
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing dma_chan_kill_bh() during channel removal and resource freeing leaves pending bottom-half work queued, leading to use-after-free and NULL pointer dereference crashes.
- [High] Lock inversion deadlock when invoking client callbacks with the channel descriptor lock held.
--

--- Patch [6]: [PATCH v2 06/64] dmaengine: fsldma: migrate tasklet to dma_chan BH ---
commit eba223ea472b760cffa1e53fb0bb48d7fa6057d5
Author: Allen Pais <[email protected]>

dmaengine: fsldma: migrate tasklet to dma_chan BH

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.

> diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
> index 22d62d958abd9..1cb6ce3270782 100644
> --- a/drivers/dma/fsldma.c
> +++ b/drivers/dma/fsldma.c
> @@ -968,18 +968,18 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)

[ ... ]

> -static void dma_do_tasklet(struct tasklet_struct *t)
> +static void dma_do_tasklet(struct dma_chan *c)
>  {
> -	struct fsldma_chan *chan = from_tasklet(chan, t, tasklet);
> +	struct fsldma_chan *chan = to_fsl_chan(c);
>  
>  	chan_dbg(chan, "tasklet entry\n");

[Severity: High]
This is a pre-existing issue, but does this cleanup path have a lock inversion
deadlock?

dma_do_tasklet() acquires chan->desc_lock before calling
fsldma_cleanup_descriptors(). While holding this lock, it invokes
fsldma_run_tx_complete_actions(), which executes the client callback via
dmaengine_desc_get_callback_invoke() and processes dependencies via
dma_run_dependencies().

If the client callback submits a new DMA transaction, or if a dependent
transaction is submitted for the same channel, it calls fsl_dma_tx_submit():

drivers/dma/fsldma.c:fsl_dma_tx_submit() {
    ...
    spin_lock_bh(&chan->desc_lock);
    ...
}

Since the non-recursive lock is already held on the same CPU, won't this
lead to a deadlock in softirq context?

> @@ -1152,7 +1152,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
>  	}
>  
>  	fdev->chan[chan->id] = chan;
> -	tasklet_setup(&chan->tasklet, dma_do_tasklet);
> +	dma_chan_init_bh(&chan->common, dma_do_tasklet);

[Severity: High]
This is a pre-existing issue, but is it possible for pending bottom-half work
to run after the channel is removed?

If an IRQ fires and queues the BH right before unbinding,
fsl_dma_chan_remove() frees the channel structure and
fsl_dma_free_chan_resources() destroys the descriptor pool without calling
dma_chan_kill_bh() (or tasklet_kill() previously).

When the pending BH work later executes dma_do_tasklet(), could it dereference
the freed channel or pass a NULL desc_pool to dma_pool_free()?

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=6