[PATCH v3 1/3] dmaengine: xilinx_dma: Fix channel idle state management in AXIDMA and MCDMA interrupt handlers

Pandey, Radhey Shyam radheys at amd.com
Sat Jun 27 09:29:07 PDT 2026


> Fix a race condition in AXIDMA and MCDMA irq handlers where the channel
> could be incorrectly marked as idle and attempt spurious transfers when
> descriptors are still being processed.
> 
> The issue occurs when:
> 1. Multiple descriptors are queued and active.
> 2. An interrupt fires after completing some descriptors.
> 3. xilinx_dma_complete_descriptor() moves completed descriptors to
> done_list.
> 4. Channel is marked idle and start_transfer() is called even though
>     active_list still contains unprocessed descriptors.
> 5. This leads to premature transfer attempts and potential descriptor
>     corruption or missed completions.
> 
> Only mark the channel as idle and start new transfers when the active list
> is actually empty, ensuring proper channel state management and avoiding
> spurious transfer attempts.
> 
> Fixes: c0bba3a99f07 ("dmaengine: vdma: Add Support for Xilinx AXI Direct Memory Access Engine")
> Tested-by: Folker Schwesinger <dev at folker-schwesinger.de>
> Signed-off-by: Suraj Gupta <suraj.gupta2 at amd.com>
> Co-developed-by: Srinivas Neeli <srinivas.neeli at amd.com>
> Signed-off-by: Srinivas Neeli <srinivas.neeli at amd.com>

Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey at amd.com>
Thanks!

> ---
>   drivers/dma/xilinx/xilinx_dma.c | 12 ++++++++----
>   1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 404235c17353..ca396b709742 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -1893,8 +1893,10 @@ static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data)
>   	if (status & XILINX_MCDMA_IRQ_IOC_MASK) {
>   		spin_lock(&chan->lock);
>   		xilinx_dma_complete_descriptor(chan);
> -		chan->idle = true;
> -		chan->start_transfer(chan);
> +		if (list_empty(&chan->active_list)) {
> +			chan->idle = true;
> +			chan->start_transfer(chan);
> +		}
>   		spin_unlock(&chan->lock);
>   	}
>   
> @@ -1950,8 +1952,10 @@ static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
>   		      XILINX_DMA_DMASR_DLY_CNT_IRQ)) {
>   		spin_lock(&chan->lock);
>   		xilinx_dma_complete_descriptor(chan);
> -		chan->idle = true;
> -		chan->start_transfer(chan);
> +		if (list_empty(&chan->active_list)) {
> +			chan->idle = true;
> +			chan->start_transfer(chan);
> +		}
>   		spin_unlock(&chan->lock);
>   	}
>   




More information about the linux-arm-kernel mailing list