mirror of
https://github.com/torvalds/linux.git
synced 2026-09-29 04:22:03 +02:00
dmaengine: xilinx_dma: Fix channel idle state management in AXIDMA and MCDMA interrupt handlers
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: c0bba3a99f ("dmaengine: vdma: Add Support for Xilinx AXI Direct Memory Access Engine")
Tested-by: Folker Schwesinger <dev@folker-schwesinger.de>
Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
Co-developed-by: Srinivas Neeli <srinivas.neeli@amd.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@amd.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Link: https://patch.msgid.link/20260626092656.1563871-2-suraj.gupta2@amd.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
678a0f8580
commit
0b6d055edb
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user