Re: [PATCH v2 01/64] dmaengine: add tasklet-backed channel BH helpers

[email protected] Mon, 27 Jul 2026 20:56:08 +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:

New issues:
- [Low] API breakage leading to widespread build failures in downstream DMA drivers due to the removal of the `task` field from `struct virt_dma_chan` without updating its consumers.

Pre-existing issues:
- [Critical] Race condition causing a Use-After-Free of a cyclic descriptor's `tx_result` pointer when a channel is concurrently terminated.
--

--- Patch [1]: [PATCH v2 01/64] dmaengine: add tasklet-backed channel BH helpers ---
commit 9141d715bfba5e26881326cc343ca063eaf8458a
Author: Allen Pais <[email protected]>

dmaengine: add tasklet-backed channel BH helpers

This patch introduces helpers to initialize, schedule, and kill a channel
bottom half. It converts virt-dma to use the new API, replacing its private
tasklet while preserving the execution context.

> diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c
> index 7961172a780dd..89fcd51ddcabe 100644
> --- a/drivers/dma/virt-dma.c
> +++ b/drivers/dma/virt-dma.c
[ ... ]
> @@ -98,7 +98,7 @@ static void vchan_complete(struct tasklet_struct *t)
>  	}
>  	spin_unlock_irq(&vc->lock);
>  
> -	dmaengine_desc_callback_invoke(&cb, &vd->tx_result);
> +	dmaengine_desc_callback_invoke(&cb, vd ? &vd->tx_result : NULL);

[Severity: Critical]
This is a pre-existing issue, but does dropping vc->lock just before
referencing vd->tx_result open a race window for a use-after-free?

If a concurrent dmaengine_terminate_sync() calls the driver's terminate_all
callback (like bcm2835_dma_terminate_all()), the driver could acquire the
lock and free vd via vchan_dma_desc_free_list():

CPU1
vchan_complete()
    spin_unlock_irq(&vc->lock);

CPU2
dmaengine_terminate_sync()
    bcm2835_dma_terminate_all()
        spin_lock_irqsave(&vc->lock, flags);
        vchan_dma_desc_free_list() // frees vd
        spin_unlock_irqrestore(&vc->lock, flags);

CPU1
    dmaengine_desc_callback_invoke(&cb, vd ? &vd->tx_result : NULL);

Could evaluating vd->tx_result here pass a dangling pointer to the client
callback if the descriptor was freed by the concurrent termination?

>  	list_for_each_entry_safe(vd, _vd, &head, node) {
>  		dmaengine_desc_get_callback(&vd->tx, &cb);
[ ... ]
> diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h
> index 59d9eabc8b674..abe2a44757442 100644
> --- a/drivers/dma/virt-dma.h
> +++ b/drivers/dma/virt-dma.h
> @@ -21,7 +21,6 @@ struct virt_dma_desc {
>  
>  struct virt_dma_chan {
>  	struct dma_chan	chan;
> -	struct tasklet_struct task;

[Severity: Low]
Does removing the task field here cause build failures in downstream drivers?

Several DMA drivers like bcm2835-dma, hisi_dma, idma64, and tegra210-adma
directly access chan->vc.task during driver removal or error paths to kill
the tasklet. Without updating those consumers, they will fail to compile.

>  	void (*desc_free)(struct virt_dma_desc *);
>  
>  	spinlock_t lock;

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