[RFC PATCH] dmaengine: xilinx_dma: Fix per-channel direction reporting via device_caps

Folker Schwesinger dev at folker-schwesinger.de
Tue Feb 17 10:49:13 PST 2026


Since commit 7e01511443c3 ("dmaengine: xilinx_dma: Set dma_device
directions") all channel directions are aggregated into
dma_device.directions so that dma_get_slave_caps() works for IIO
DMAEngine buffers.

However, this caused a regression in ASoC audio on ZynqMP platforms,
that causes cyclic playback to fail after the first buffer period,
because ASoC dmaengine PCM expects fixed per-channel direction reporting
from dma_get_slave_caps().

Implement optional device_caps() callback and override caps->directions
with the channel's fixed direction. This keeps device-wide direction
reporting for IIO intact while restoring correct per-channel semantics
for ASoC.
Other dma_slave_caps fields are left unchanged from their respective
values initialized from dma_get_slave_caps(). In case there should ever
be the need to override other fields, these can be added later.

Fixes: 7e01511443c3 ("dmaengine: xilinx_dma: Set dma_device directions")
Cc: stable at vger.kernel.org
Reported-by: Rahul Navale <rahul.navale at ifm.com>
Closes: https://lore.kernel.org/dmaengine/20260211140051.8177-1-rahulnavale04@gmail.com/T/#u
Closes: https://lore.kernel.org/dmaengine/CY1PR12MB96978AEBD6072FC469DFEAF1B762A@CY1PR12MB9697.namprd12.prod.outlook.com/T/#u
Signed-off-by: Folker Schwesinger <dev at folker-schwesinger.de>

---
Posting this as RFC because I can't verify this actually fixes the
regression as I don't have a ZynqMP. So Rahul, could you test if this
fixes the issue and report back? BR F.
---
 drivers/dma/xilinx/xilinx_dma.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 64b3fba4e44f..bdd16173d762 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -1711,6 +1711,19 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan)
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
 
+/**
+ * xilinx_dma_device_caps - Write channel-specific DMA slave capabilities
+ * @dchan: DMA channel
+ * @caps: DMA slave capabilities of DMA channel
+ */
+static void xilinx_dma_device_caps(struct dma_chan *dchan,
+				   struct dma_slave_caps *caps)
+{
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+
+	caps->directions = chan->direction;
+}
+
 /**
  * xilinx_dma_device_config - Configure the DMA channel
  * @dchan: DMA channel
@@ -3292,6 +3305,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.device_tx_status = xilinx_dma_tx_status;
 	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
 	xdev->common.device_config = xilinx_dma_device_config;
+	xdev->common.device_caps = xilinx_dma_device_caps;
 	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask);
 		xdev->common.device_prep_peripheral_dma_vec = xilinx_dma_prep_peripheral_dma_vec;

base-commit: ab736ed52e3409b58a4888715e4425b6e8ac444f
-- 
2.53.0



More information about the linux-arm-kernel mailing list