Re: [PATCH] dmaengine: tegra: initialize channel state before requesting IRQ
From: Frank Li
Date: Fri Oct 16 2026 - 14:09:36 EST
On Sun, Aug 30, 2026 at 02:12:13PM +0800, Runyu Xiao wrote:
> tegra_dma_probe() registers a channel IRQ before initializing the
> channel lock, tasklet, waitqueue, and descriptor lists used by the
> interrupt path. A pending interrupt can therefore access uninitialized
> channel state.
>
> Prepare the channel state before requesting its IRQ so the handler and
> tasklet always see initialized synchronization and list objects.
>
> Fixes: ec8a1586780c ("dma: tegra: add dmaengine based dma driver")
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: Codex:GPT-5
> Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
> ---
Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
> drivers/dma/tegra20-apb-dma.c | 25 +++++++++++++------------
> 1 file changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
> index 640b8a218..23fd294ab 100644
> --- a/drivers/dma/tegra20-apb-dma.c
> +++ b/drivers/dma/tegra20-apb-dma.c
> @@ -1494,6 +1494,19 @@ static int tegra_dma_probe(struct platform_device *pdev)
> }
>
> snprintf(tdc->name, sizeof(tdc->name), "apbdma.%d", i);
> + tdc->tdma = tdma;
> + tdc->id = i;
> + tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID;
> +
> + tasklet_setup(&tdc->tasklet, tegra_dma_tasklet);
> + spin_lock_init(&tdc->lock);
> + init_waitqueue_head(&tdc->wq);
> +
> + INIT_LIST_HEAD(&tdc->pending_sg_req);
> + INIT_LIST_HEAD(&tdc->free_sg_req);
> + INIT_LIST_HEAD(&tdc->free_dma_desc);
> + INIT_LIST_HEAD(&tdc->cb_desc);
> +
> ret = devm_request_irq(&pdev->dev, irq, tegra_dma_isr, 0,
> tdc->name, tdc);
> if (ret) {
> @@ -1507,18 +1520,6 @@ static int tegra_dma_probe(struct platform_device *pdev)
> dma_cookie_init(&tdc->dma_chan);
> list_add_tail(&tdc->dma_chan.device_node,
> &tdma->dma_dev.channels);
> - tdc->tdma = tdma;
> - tdc->id = i;
> - tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID;
> -
> - tasklet_setup(&tdc->tasklet, tegra_dma_tasklet);
> - spin_lock_init(&tdc->lock);
> - init_waitqueue_head(&tdc->wq);
> -
> - INIT_LIST_HEAD(&tdc->pending_sg_req);
> - INIT_LIST_HEAD(&tdc->free_sg_req);
> - INIT_LIST_HEAD(&tdc->free_dma_desc);
> - INIT_LIST_HEAD(&tdc->cb_desc);
> }
>
> dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
> --
> 2.34.1