Re: [PATCH v2 15/64] dmaengine: pch_dma: convert tasklet to dma_chan BH
[email protected] Mon, 27 Jul 2026 20:57:15 +0000
| Newsgroups | org.kernel.vger.dmaengine |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: Pre-existing issues: - [High] Missing cleanup of scheduled BH work on the probe error path can lead to a use-after-free. - [High] Early registration of a shared IRQ before channel count setup leads to an unhandled IRQ storm. - [High] Client completion callbacks are invoked with the channel spinlock held, leading to a potential self-deadlock. - [High] Process-context functions acquire the channel spinlock without disabling softirqs, risking a deadlock if preempted by the BH work. - [High] Checking hardware idle state outside the lock causes a TOCTOU race leading to premature completion and use-after-free. -- --- Patch [15]: [PATCH v2 15/64] dmaengine: pch_dma: convert tasklet to dma_chan BH --- commit a2ed59e859fb44b7074fd4693b53c278ebc94f3d Author: Allen Pais <[email protected]> dmaengine: pch_dma: convert 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/pch_dma.c b/drivers/dma/pch_dma.c > index bf805f1024f64..b0044bea8fe4c 100644 > --- a/drivers/dma/pch_dma.c > +++ b/drivers/dma/pch_dma.c [ ... ] > @@ -665,9 +664,10 @@ static int pd_device_terminate_all(struct dma_chan *chan) > return 0; > } > > -static void pdc_tasklet(struct tasklet_struct *t) > +static void pdc_tasklet(struct dma_chan *c) > { > - struct pch_dma_chan *pd_chan = from_tasklet(pd_chan, t, tasklet); > + struct pch_dma_chan *pd_chan = container_of(c, struct pch_dma_chan, > + chan); > unsigned long flags; > > if (!pdc_is_idle(pd_chan)) { [Severity: High] This isn't a bug introduced by this patch, but might checking the hardware idle state outside the lock cause a race condition? If a concurrent pd_issue_pending() acquires the lock first and starts the next request, could the preempted thread later acquire the lock, see a stale idle state, and improperly complete the newly started descriptor? This same check appears unprotected in pd_issue_pending(): drivers/dma/pch_dma.c:pd_issue_pending() { ... if (pdc_is_idle(pd_chan)) { ... } [Severity: High] This is a pre-existing issue, but would acquiring the channel lock with a plain spin_lock() in process-context functions risk a deadlock? If a hardware interrupt preempts process context here in pd_tx_submit() or pd_issue_pending(): drivers/dma/pch_dma.c:pd_tx_submit() { ... spin_lock(&pd_chan->lock); ... } and schedules this pdc_tasklet() work which attempts to acquire the exact same lock using spin_lock_irqsave(), might this deadlock the CPU? [Severity: High] This is a pre-existing issue, but is there a risk of a self-deadlock if the client callback submits a new DMA transaction? If pdc_tasklet() acquires the lock, and then pdc_chain_complete() invokes the callback: drivers/dma/pch_dma.c:pdc_chain_complete() { ... if (callback) callback(param); ... } and that callback attempts to submit a new transaction via pd_tx_submit(), it will attempt to acquire the same pd_chan->lock. [ ... ] > @@ -877,7 +877,7 @@ static int pch_dma_probe(struct pci_dev *pdev, > INIT_LIST_HEAD(&pd_chan->queue); > INIT_LIST_HEAD(&pd_chan->free_list); > > - tasklet_setup(&pd_chan->tasklet, pdc_tasklet); > + dma_chan_init_bh(&pd_chan->chan, pdc_tasklet); > list_add_tail(&pd_chan->chan.device_node, &pd->dma.channels); > } [Severity: High] This isn't a bug introduced by this patch, but can requesting the shared IRQ before dma_async_device_register() initializes the channel count lead to an unhandled IRQ storm? In pch_dma_probe(), request_irq() is called with IRQF_SHARED before the channel count is initialized. The interrupt handler relies entirely on pd->dma.chancnt: drivers/dma/pch_dma.c:pd_irq() { ... for (i = 0; i < pd->dma.chancnt; i++) { ... } If pd->dma.chancnt is initially 0, could it loop 0 times and return IRQ_NONE without clearing the hardware interrupt status? [Severity: High] This is a pre-existing issue, but does the probe error path fail to kill the scheduled bottom-half work before freeing the device structure? If dma_async_device_register() fails, the error path frees the memory but appears to skip cancelling pending BH works: drivers/dma/pch_dma.c:pch_dma_probe() { ... err_free_pool: dma_pool_destroy(pd->pool); err_free_irq: free_irq(pdev->irq, pd); ... } If an interrupt fires and schedules the BH work during this window, could it execute on freed memory? [ ... ] -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=15