Re: [RFC PATCH] dmaengine: xilinx_dma: Fix per-channel direction reporting via device_caps
From: Folker Schwesinger
Date: Wed Mar 04 2026 - 09:50:42 EST
On Wed Mar 4, 2026 at 9:35 AM CET, Rahul Navale wrote:
>
> <4>[ 0.302360] dma_slave_caps:
> <4>[ 0.302364] src_addr_widths = 0x00000000
> <4>[ 0.302368] dst_addr_widths = 0x00000000
> <4>[ 0.302371] directions = 0x00000000
> <4>[ 0.302374] min_burst = 0x00000000
> <4>[ 0.302377] max_burst = 0x00000000
> <4>[ 0.302380] max_sg_burst = 0x00000000
> <4>[ 0.302383] cmd_pause = 0x00
> <4>[ 0.302386] cmd_resume = 0x00
> <4>[ 0.302388] cmd_terminate = 0x00
> <4>[ 0.302391] residue_granularity= 0x00000000
> <4>[ 0.302394] descriptor_reuse = 0x00
> <4>[ 0.302398] xilinx_dma_device_caps: caps->directions = 0x00000001
> <4>[ 0.302401] xilinx_dma_device_caps: caps->directions = 0x00000001
> <4>[ 0.302404] dma_slave_caps:
> <4>[ 0.302406] src_addr_widths = 0x00000000
> <4>[ 0.302409] dst_addr_widths = 0x00000000
> <4>[ 0.302412] directions = 0x00000001
> <4>[ 0.302415] min_burst = 0x00000000
> <4>[ 0.302418] max_burst = 0x00000000
> <4>[ 0.302421] max_sg_burst = 0x00000000
> <4>[ 0.302423] cmd_pause = 0x00
> <4>[ 0.302426] cmd_resume = 0x00
> <4>[ 0.302429] cmd_terminate = 0x01
> <4>[ 0.302431] residue_granularity= 0x00000001
> <4>[ 0.302434] descriptor_reuse = 0x00
I think the issue stems from the difference in residue_granularity
(directions is set in xilinx_dma_device_caps and playback is still fixed
and cmd_terminate is only referenced in the code by some unrelated
driver).
>From a quick trace through the code I found that in the Xilinx DMA
residue_granularity is set for AXIDMA independently from the SG setting
of the DMA core [1].
However, in xilinx_dma_tx_status() one of the conditions for residue
calculations is that SG mode is enabled [2].
Here's a quick patch that defers setting residue_granularity for the
device into channel probe until chan->has_sg is available. Could you
test if this fixes your issue (and of course re-activate all the caps->
assignments in dma_get_slave_caps(), keep the debug stuff for now)?
<-->8-->
diff --git i/drivers/dma/xilinx/xilinx_dma.c w/drivers/dma/xilinx/xilinx_dma.c
index fabff602065f..adae1b37b533 100644
--- i/drivers/dma/xilinx/xilinx_dma.c
+++ w/drivers/dma/xilinx/xilinx_dma.c
@@ -3039,6 +3039,14 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
str_enabled_disabled(chan->has_sg));
}
+ /* Residue calculation is supported by only AXI DMA and CDMA */
+ if(chan->has_sg && (
+ xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA ||
+ xdev->dma_config->dmatype == XDMA_TYPE_CDMA)) {
+ xdev->common.residue_granularity =
+ DMA_RESIDUE_GRANULARITY_SEGMENT;
+ }
+
/* Initialize the tasklet */
tasklet_setup(&chan->tasklet, xilinx_dma_do_tasklet);
@@ -3277,15 +3285,9 @@ static int xilinx_dma_probe(struct platform_device *pdev)
xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
xdev->common.device_prep_dma_cyclic =
xilinx_dma_prep_dma_cyclic;
- /* Residue calculation is supported by only AXI DMA and CDMA */
- xdev->common.residue_granularity =
- DMA_RESIDUE_GRANULARITY_SEGMENT;
} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
- /* Residue calculation is supported by only AXI DMA and CDMA */
- xdev->common.residue_granularity =
- DMA_RESIDUE_GRANULARITY_SEGMENT;
} else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
xdev->common.device_prep_slave_sg = xilinx_mcdma_prep_slave_sg;
} else {
<--8<-->
[1]: https://elixir.bootlin.com/linux/v6.19.3/source/drivers/dma/xilinx/xilinx_dma.c#L3284
[2]: https://elixir.bootlin.com/linux/v6.19.3/source/drivers/dma/xilinx/xilinx_dma.c#L1293