[PATCH] dmaengine: xilinx: xilinx_dma: Fix residue calculation for cyclic DMA
Marek Vasut
marex at nabladev.com
Mon Mar 16 15:18:57 PDT 2026
The cyclic DMA calculation is currently entirely broken and reports
residue only for the first segment. The problem is twofold.
First, when the first descriptor finishes, it is moved from active_list
to done_list, but it is never returned back into the active_list. The
xilinx_dma_tx_status() expects the descriptor to be in the active_list
to report any meaningful residue information, which never happens after
the first descriptor finishes. Fix this up in xilinx_dma_start_transfer()
and if the descriptor is cyclic, lift it from done_list and place it back
into active_list list.
Second, the segment .status fields of the descriptor remain dirty. Once
the DMA did one pass on the descriptor, the .status fields are populated
with data by the DMA, but the .status fields are not cleared before reuse
during the next cyclic DMA round. The xilinx_dma_get_residue() recognizes
that as if the descriptor was complete and had 0 residue, which is bogus.
Reinitialize the status field before placing the descriptor back into the
active_list.
Fixes: c0bba3a99f07 ("dmaengine: vdma: Add Support for Xilinx AXI Direct Memory Access Engine")
Signed-off-by: Marek Vasut <marex at nabladev.com>
---
Cc: Michal Simek <michal.simek at amd.com>
Cc: Radhey Shyam Pandey <radhey.shyam.pandey at amd.com>
Cc: Rahul Navale <rahul.navale at ifm.com>
Cc: Sasha Levin <sashal at kernel.org>
Cc: Suraj Gupta <suraj.gupta2 at amd.com>
Cc: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>
Cc: Vinod Koul <vkoul at kernel.org>
Cc: dmaengine at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
---
drivers/dma/xilinx/xilinx_dma.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 6b0927e3d684b..6e8e348973a9e 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -1564,8 +1564,29 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
if (chan->err)
return;
- if (list_empty(&chan->pending_list))
+ if (list_empty(&chan->pending_list)) {
+ if (chan->cyclic) {
+ struct xilinx_dma_tx_descriptor *desc;
+ struct list_head *entry;
+
+ desc = list_last_entry(&chan->done_list,
+ struct xilinx_dma_tx_descriptor, node);
+ list_for_each(entry, &desc->segments) {
+ struct xilinx_axidma_tx_segment *axidma_seg;
+ struct xilinx_axidma_desc_hw *axidma_hw;
+ axidma_seg = list_entry(entry,
+ struct xilinx_axidma_tx_segment,
+ node);
+ axidma_hw = &axidma_seg->hw;
+ axidma_hw->status = 0;
+ }
+
+ list_splice_tail_init(&chan->done_list, &chan->active_list);
+ chan->desc_pendingcount = 0;
+ chan->idle = false;
+ }
return;
+ }
if (!chan->idle)
return;
--
2.51.0
More information about the linux-arm-kernel
mailing list