Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dmaengine: ste_dma40: Keep prepared descriptors across termination
@ 2026-11-04 21:28 Linus Walleij
  2026-11-12 20:59 ` Frank Li
  0 siblings, 1 reply; 2+ messages in thread
From: Linus Walleij @ 2026-11-04 21:28 UTC (permalink / raw)
  To: Vinod Koul, Frank Li
  Cc: linux-arm-kernel, dmaengine, Ulf Hansson, Linus Walleij

MMCI can prepare the next request while the current DMA transfer is
running. If the current request fails, its error handler terminates the
channel before the next descriptor has been submitted.

d40_term_all() frees that descriptor from prepare_queue, although MMCI
still holds its pointer. Submitting it later accesses freed memory in
d40_tx_submit(). A reported crash writes to 0x104 through a list pointer
containing LIST_POISON1, which is consistent with this sequence.

Termination only cancels transfers that have been submitted. Leave
prepared descriptors on prepare_queue so the client can still submit
them, and release any remaining prepared descriptors when the channel
resources are freed. Keep tracking them so abandoned descriptors are
reclaimed at channel teardown.

Fixes: 82babbb361f2 ("dmaengine/ste_dma40: fix memory leak due to prepared descriptors")
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 drivers/dma/ste_dma40.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 74dd4cbdc3c0..f1cbc719c4f0 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1166,14 +1166,6 @@ static void d40_term_all(struct d40_chan *d40c)
 			d40_desc_free(d40c, d40d);
 		}
 
-	/* Release descriptors in prepare queue */
-	if (!list_empty(&d40c->prepare_queue))
-		list_for_each_entry_safe(d40d, _d,
-					 &d40c->prepare_queue, node) {
-			d40_desc_remove(d40d);
-			d40_desc_free(d40c, d40d);
-		}
-
 	d40c->pending_tx = 0;
 }
 
@@ -2222,7 +2214,8 @@ static int d40_config_memcpy(struct d40_chan *d40c)
 
 static int d40_free_dma(struct d40_chan *d40c)
 {
-
+	struct d40_desc *d40d;
+	struct d40_desc *_d;
 	int res = 0;
 	u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type);
 	struct d40_phy_res *phy = d40c->phy_chan;
@@ -2252,6 +2245,12 @@ static int d40_free_dma(struct d40_chan *d40c)
 	/* Release descriptor state; this does not access DMA40 registers. */
 	d40_term_all(d40c);
 
+	/* Release any prepared descriptors the client did not submit. */
+	list_for_each_entry_safe(d40d, _d, &d40c->prepare_queue, node) {
+		d40_desc_remove(d40d);
+		d40_desc_free(d40c, d40d);
+	}
+
 	res = pm_runtime_resume_and_get(d40c->base->dev);
 	if (res >= 0) {
 		res = d40_channel_execute_command(d40c, D40_DMA_STOP);
@@ -2508,10 +2507,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
 		goto free_desc;
 	}
 
-	/*
-	 * add descriptor to the prepare queue in order to be able
-	 * to free them later in terminate_all
-	 */
+	/* Track prepared descriptors until submission or channel release. */
 	list_add_tail(&desc->node, &chan->prepare_queue);
 
 	spin_unlock_irqrestore(&chan->lock, flags);

---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261104-dma40-fixes-d9db6094b7d9

Best regards,
--  
Linus Walleij <linusw@kernel.org>



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-12 21:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 21:28 [PATCH] dmaengine: ste_dma40: Keep prepared descriptors across termination Linus Walleij
2026-11-12 20:59 ` Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox