[PATCH 1/7] dmaengine: xilinx_dma: Fix MCDMA descriptor fields for MM2S vs S2MM

Srinivas Neeli srinivas.neeli at amd.com
Thu Feb 12 05:51:40 PST 2026


The MCDMA BD format differs between MM2S and S2MM directions, but the
driver was using generic 'status' and 'sideband_status' fields for both.
This could lead to incorrect residue calculations when the hardware
updates direction-specific fields.

Refactor the descriptor structure to use unions with direction-specific
field names (mm2s_status/s2mm_status, etc.). This ensures the driver
accesses the correct hardware fields based on channel direction and
matches the hardware documentation.

Fixes: 6ccd692bfb7f ("dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support")
Signed-off-by: Srinivas Neeli <srinivas.neeli at amd.com>
---
 drivers/dma/xilinx/xilinx_dma.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 53229d8ebc52..e09a22721c01 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -275,8 +275,10 @@ struct xilinx_axidma_desc_hw {
  * @buf_addr_msb: MSB of Buffer address @0x0C
  * @rsvd: Reserved field @0x10
  * @control: Control Information field @0x14
- * @status: Status field @0x18
- * @sideband_status: Status of sideband signals @0x1C
+ * @mm2s_ctrl_sideband: Sideband control info for mm2s @0x18
+ * @s2mm_status: Status field for s2mm @0x18
+ * @mm2s_status: Status field for mm2s @0x1C
+ * @s2mm_sideband_status: Sideband status for s2mm @0x1C
  * @app: APP Fields @0x20 - 0x30
  */
 struct xilinx_aximcdma_desc_hw {
@@ -286,8 +288,14 @@ struct xilinx_aximcdma_desc_hw {
 	u32 buf_addr_msb;
 	u32 rsvd;
 	u32 control;
-	u32 status;
-	u32 sideband_status;
+	union {
+		u32 mm2s_ctrl_sideband;
+		u32 s2mm_status;
+	};
+	union {
+		u32 mm2s_status;
+		u32 s2mm_sideband_status;
+	};
 	u32 app[XILINX_DMA_NUM_APP_WORDS];
 } __aligned(64);
 
@@ -1013,9 +1021,16 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
 					   struct xilinx_aximcdma_tx_segment,
 					   node);
 			aximcdma_hw = &aximcdma_seg->hw;
-			residue +=
-				(aximcdma_hw->control - aximcdma_hw->status) &
-				chan->xdev->max_buffer_len;
+			if (chan->direction == DMA_DEV_TO_MEM)
+				residue +=
+					(aximcdma_hw->control -
+					 aximcdma_hw->s2mm_status) &
+					chan->xdev->max_buffer_len;
+			else
+				residue +=
+					(aximcdma_hw->control -
+					 aximcdma_hw->mm2s_status) &
+					chan->xdev->max_buffer_len;
 		}
 	}
 
-- 
2.25.1




More information about the linux-arm-kernel mailing list