Re: [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH
[email protected] Mon, 27 Jul 2026 20:54:08 +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: Pre-existing issues: - [High] On channel error, the driver incorrectly marks the currently active descriptor as successful and silently drops all other pending descriptors, causing clients to hang indefinitely. - [High] The DMA completion handler `zynqmp_dma_chan_desc_cleanup` drops `chan->lock` during callback execution while using `list_for_each_entry_safe`, allowing list corruption if a callback calls `dmaengine_terminate_async`. - [High] `zynqmp_dma_device_terminate_all` fails to actually halt the hardware DMA engine, leading to hardware silently overwriting memory after the client assumes the transfer is stopped. -- --- Patch [21]: [PATCH v2 21/64] dmaengine: zynqmp-dma: switch completion tasklet to dma_chan BH --- commit c7b5b53ae6dbca9c51452b38046b4252492aa34c Author: Allen Pais <[email protected]> Subject: dmaengine: zynqmp-dma: switch completion 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/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c > index f6a812e49ddca..6291126cdc9f8 100644 > --- a/drivers/dma/xilinx/zynqmp_dma.c > +++ b/drivers/dma/xilinx/zynqmp_dma.c [ ... ] > @@ -760,11 +758,12 @@ static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data) > > /** > * zynqmp_dma_do_tasklet - Schedule completion tasklet > - * @t: Pointer to the ZynqMP DMA channel structure > + * @c: Pointer to the ZynqMP DMA channel structure > */ > -static void zynqmp_dma_do_tasklet(struct tasklet_struct *t) > +static void zynqmp_dma_do_tasklet(struct dma_chan *c) > { > - struct zynqmp_dma_chan *chan = from_tasklet(chan, t, tasklet); > + struct zynqmp_dma_chan *chan = container_of(c, > + struct zynqmp_dma_chan, common); > u32 count; > unsigned long irqflags; > [Severity: High] This isn't a bug introduced by this patch, but I noticed a potential problem in how channel errors are handled when this bottom half runs. When chan->err is set, we call zynqmp_dma_reset(). Inside zynqmp_dma_reset(): drivers/dma/xilinx/zynqmp_dma.c:zynqmp_dma_reset() { ... zynqmp_dma_complete_descriptor(chan); ... zynqmp_dma_free_descriptors(chan); ... } Does this incorrectly move the active descriptor to done_list and mark it successful? Also, it appears zynqmp_dma_free_descriptors() silently moves all remaining descriptors from active_list and pending_list to the free_list without invoking their callbacks. Could this cause clients waiting on these DMA transfers to hang indefinitely? [Severity: High] This is a pre-existing issue, but could there be a list corruption risk in zynqmp_dma_chan_desc_cleanup() which is called shortly after in this bottom half? drivers/dma/xilinx/zynqmp_dma.c:zynqmp_dma_chan_desc_cleanup() { ... list_for_each_entry_safe(desc, next, &chan->done_list, node) { ... if (dmaengine_desc_callback_valid(&cb)) { spin_unlock_irqrestore(&chan->lock, irqflags); dmaengine_desc_callback_invoke(&cb, NULL); spin_lock_irqsave(&chan->lock, irqflags); } ... } The lock is dropped during callback execution. If the client calls dmaengine_terminate_async() in the callback, all descriptors (including those on done_list) are moved to free_list. When the lock is reacquired, the loop continues using the next pointer which is now on the free_list. Could this lead to double-frees and traversing invalid entries? [Severity: High] This is a pre-existing issue, but does zynqmp_dma_device_terminate_all() actually halt the hardware DMA engine? drivers/dma/xilinx/zynqmp_dma.c:zynqmp_dma_device_terminate_all() { ... writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS); zynqmp_dma_free_descriptors(chan); ... } It masks interrupts and frees software descriptors, but doesn't seem to clear the ZYNQMP_DMA_ENABLE bit or issue a hardware reset. If the hardware controller remains active, could it silently overwrite memory after the client assumes the transfer is stopped and unmaps the DMA buffers? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=21