DMA Engine development
 help / color / mirror / Atom feed
* [PATCH] dmaengine: at_xdmac: handle empty transfer list in tx_status
@ 2026-11-15  8:02 Ziheng Wei
  2026-11-15  8:19 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Ziheng Wei @ 2026-11-15  8:02 UTC (permalink / raw)
  To: Ludovic Desroches, Vinod Koul
  Cc: Frank Li, dmaengine, linux-arm-kernel, linux-kernel, stable

at_xdmac_device_terminate_all() removes every descriptor from
atchan->xfers_list without completing their cookies, so
dma_cookie_status() keeps reporting a terminated cookie as
DMA_IN_PROGRESS. at_xdmac_tx_status() then calls list_first_entry()
on the empty list and uses the list head, which lives inside struct
at_xdmac_chan, as a descriptor: active_xfer and xfer_size are read
from neighbouring channel fields, and if active_xfer happens to be
non-zero the residue loop walks a descs_list made of those fields.

For audio this is a routine path. The generic dmaengine PCM calls
dmaengine_terminate_async() on TRIGGER_STOP and later
dmaengine_tx_status() on the same cookie from
snd_dmaengine_pcm_sync_stop() and on close. What happens depends on
the struct layout. On a 32-bit build active_xfer overlays
sconfig.device_fc, which is normally false, so only a bogus residue
is reported. With CONFIG_DEBUG_SPINLOCK the larger spinlock_t puts
active_xfer on the held lock word and descs_list on the owner_cpu and
owner fields, so the loop follows a pointer that is not a descriptor.

Report a residue of 0 when no descriptor is queued.

Found by LLM-assisted source review. Not tested on hardware; the
layout analysis above is from reading the code only.

Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel eXtended DMA Controller driver")
Cc: stable@vger.kernel.org
Signed-off-by: Ziheng Wei <zihengw03@163.com>
---

Notes:
    The changelog was drafted with an AI assistant from my analysis;
    I have reviewed the code, the fix and the text.

 drivers/dma/at_xdmac.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index ef0dfe9d3..bcfbb41ea 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1553,7 +1553,16 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 
 	spin_lock_irqsave(&atchan->lock, flags);
 
-	desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
+	desc = list_first_entry_or_null(&atchan->xfers_list, struct at_xdmac_desc,
+					xfer_node);
+	/*
+	 * The list is empty once the channel has been terminated, while the
+	 * cookie of the terminated transfer is still reported as in progress.
+	 */
+	if (!desc) {
+		dma_set_residue(txstate, 0);
+		goto spin_unlock;
+	}
 
 	/*
 	 * If the transfer has not been started yet, don't need to compute the

base-commit: 97d73c8251226cf27cc6656b4c542869bb8c69fa
-- 
2.43.0


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

end of thread, other threads:[~2026-11-15  8:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-15  8:02 [PATCH] dmaengine: at_xdmac: handle empty transfer list in tx_status Ziheng Wei
2026-11-15  8:19 ` sashiko-bot

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