Re: [PATCH v2 24/64] dmaengine: txx9dmac: route callbacks via channel BH

[email protected] Mon, 27 Jul 2026 21:00:11 +0000
Newsgroups org.kernel.vger.dmaengine
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Uninitialized BH work and missing cleanup in shared IRQ mode
- [High] Interrupt storm and livelock due to premature IRQ unmasking in shared IRQ mode
- [High] Invalid `enable_irq()` parameter in shared IRQ mode
--

--- Patch [24]: [PATCH v2 24/64] dmaengine: txx9dmac: route callbacks via channel BH ---
commit ba661d7c1d6f85fdbcef7fb4031ee54ec6ee5c5a
Author: Allen Pais <[email protected]>

dmaengine: txx9dmac: route callbacks via channel BH

Use the per-channel BH helpers for descriptor completion handling and
schedule per-channel work from both channel and controller IRQ paths.

> diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
> index 05622b68a9363..6269baa28c513 100644
> --- a/drivers/dma/txx9dmac.c
> +++ b/drivers/dma/txx9dmac.c
> @@ -601,13 +601,13 @@ static void txx9dmac_scan_descriptors(struct txx9dmac_chan *dc)
>  	}
>  }
>  
> -static void txx9dmac_chan_tasklet(struct tasklet_struct *t)
> +static void txx9dmac_chan_tasklet(struct dma_chan *chan)
>  {
>  	int irq;
>  	u32 csr;
>  	struct txx9dmac_chan *dc;
>  
> -	dc = from_tasklet(dc, t, tasklet);
> +	dc = container_of(chan, struct txx9dmac_chan, chan);
>  	csr = channel_readl(dc, CSR);
>  	dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", csr);
>  

[Severity: High]
Does this code handle shared IRQs correctly?

When running in shared IRQ mode, dc->irq is set to -1. Now that the shared
controller path schedules this channel BH, txx9dmac_chan_tasklet() will run
and unconditionally call enable_irq(dc->irq) at the end of the function:

    irq = dc->irq;
    enable_irq(irq);

Could this end up calling enable_irq(-1) and causing an issue in the core IRQ
code?

[ ... ]

> @@ -659,7 +659,7 @@ static void txx9dmac_tasklet(struct tasklet_struct *t)
>  			spin_lock(&dc->lock);
>  			if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC |
>  				   TXX9_DMA_CSR_NTRNFC))
> -				txx9dmac_scan_descriptors(dc);
> +				dma_chan_schedule_bh(&dc->chan);
>  			spin_unlock(&dc->lock);
>  		}
>  	}

[Severity: High]
Could this result in an interrupt storm?

Previously, txx9dmac_scan_descriptors() would synchronously clear the hardware
interrupt condition before the shared tasklet unmasked the IRQ. 

Now, the work is deferred to the async BH handler, but enable_irq(irq) is
still called synchronously at the end of txx9dmac_tasklet():

    irq = ddev->irq;
    enable_irq(irq);

Will the unmasked IRQ immediately fire again before the BH has a chance to run
and clear the hardware interrupt condition?

[ ... ]

> @@ -1113,7 +1113,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
>  		irq = platform_get_irq(pdev, 0);
>  		if (irq < 0)
>  			return irq;
> -		tasklet_setup(&dc->tasklet, txx9dmac_chan_tasklet);
> +		dma_chan_init_bh(&dc->chan, txx9dmac_chan_tasklet);
>  		dc->irq = irq;
>  		err = devm_request_irq(&pdev->dev, dc->irq,
>  			txx9dmac_chan_interrupt, 0, dev_name(&pdev->dev), dc);

[Severity: High]
Is the BH work properly initialized when operating in shared IRQ mode?

dma_chan_init_bh() is only called if dc->ddev->irq < 0:

    if (dc->ddev->irq < 0) {
        ...
        dma_chan_init_bh(&dc->chan, txx9dmac_chan_tasklet);
        ...
    } else {
        dc->irq = -1;
    }

If the controller uses a shared IRQ, the BH work remains uninitialized.
When the shared controller tasklet attempts to schedule it, will it trigger a
WARN_ON(!chan->bh_work_initialized) and drop the completion request entirely?

[ ... ]

> @@ -1159,7 +1159,7 @@ static void txx9dmac_chan_remove(struct platform_device *pdev)
>  	dma_async_device_unregister(&dc->dma);
>  	if (dc->irq >= 0) {
>  		devm_free_irq(&pdev->dev, dc->irq, dc);
> -		tasklet_kill(&dc->tasklet);
> +		dma_chan_kill_bh(&dc->chan);
>  	}
>  	dc->ddev->chan[pdev->id % TXX9_DMA_MAX_NR_CHANNELS] = NULL;
>  }

[Severity: High]
Could we leak resources here in shared IRQ mode?

Similar to the probe function, the cleanup relies on dc->irq >= 0. If the
initialization issue above is fixed so the BH work is correctly used in shared
IRQ mode, dma_chan_kill_bh() would still be skipped here since dc->irq is -1.

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