Re: [PATCH v2] dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all
From: Hongling Zeng
Date: Tue Jun 16 2026 - 22:30:11 EST
Hi Frank and Jernej Skrabec:
Thanks for all the review!
You're absolutely right.After checking virt-dma.h, I see that desc_terminated is the correct queue for actively terminated transfers. I'll update to use:
- vchan_terminate_vdesc(vd);
I'll send v3 ,Please help to review.
Best regards,
Hongling Zeng
在 2026年06月17日 04:47, Frank Li 写道:
On Tue, Jun 16, 2026 at 02:04:49PM +0800, Hongling Zeng wrote:
When terminating a non-cyclic DMA transfer, the active descriptorshould It be in desc_terminated queue?
is not properly reclaimed. The descriptor is removed from the
desc_issued list in sun6i_dma_start_desc(), but in
sun6i_dma_terminate_all(), only cyclic transfer descriptors are
added to the desc_completed list before cleanup.
For non-cyclic transfers, pchan->desc is set to NULL without first
adding the descriptor back to a list that vchan_get_all_descriptors()
can collect. This causes the descriptor and its associated LLI chain
to be permanently leaked.
Fix by ensuring both cyclic and non-cyclic active descriptors are
added to the desc_completed list before setting pchan->desc to NULL.
Fixes: 555859308723 ("dmaengine: sun6i: Add driver for the Allwinner A31 DMA controller")
Signed-off-by: Hongling Zeng <zenghongling@xxxxxxxxxx>
---
Change in v2;
-Add pchan->desc != pchan->done check to prevent race condition
where completed descriptors could be double-added to desc_completed
list, causing list corruption
---
drivers/dma/sun6i-dma.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 7a79f346250a..12d038ef5f2e 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -946,16 +946,14 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
spin_lock_irqsave(&vchan->vc.lock, flags);
- if (vchan->cyclic) {
- vchan->cyclic = false;
- if (pchan && pchan->desc) {
- struct virt_dma_desc *vd = &pchan->desc->vd;
- struct virt_dma_chan *vc = &vchan->vc;
+ if (pchan && pchan->desc && pchan->desc != pchan->done) {
+ struct virt_dma_desc *vd = &pchan->desc->vd;
+ struct virt_dma_chan *vc = &vchan->vc;
- list_add_tail(&vd->node, &vc->desc_completed);
- }
+ list_add_tail(&vd->node, &vc->desc_completed);
ref: https://lore.kernel.org/dmaengine/ajETw7uwVx_U9o5F@ryzen/T/#m541c24b45fb425c6a8a81d800db225b58411447e
Frank
}
+ vchan->cyclic = false;
vchan_get_all_descriptors(&vchan->vc, &head);
if (pchan) {
--
2.25.1