[PATCH v5 4/5] dmaengine: dw-axi-dmac: use atomic polling for suspend acknowledgment

From: James Hilliard

Date: Fri Nov 13 2026 - 04:59:12 EST


The pause loop delays after its final status read, so an acknowledgment
that arrives during that delay is cleared without being observed and
the caller receives -EAGAIN.

Use readx_poll_timeout_atomic() to check the status after the final delay.
Keep the two-microsecond polling interval, 40-microsecond timeout and
-EAGAIN return value when suspension is not acknowledged.

Fixes: 1fe20f1b8454 ("dmaengine: Introduce DW AXI DMAC driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index 040c12d07db2..1a53fbc951a9 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1219,7 +1219,8 @@ static int dma_chan_pause(struct dma_chan *dchan)
{
struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
unsigned long flags;
- unsigned int timeout = 20; /* timeout iterations */
+ u32 status;
+ int ret;
u64 val;

spin_lock_irqsave(&chan->vc.lock, flags);
@@ -1250,12 +1251,9 @@ static int dma_chan_pause(struct dma_chan *dchan)
}
}

- do {
- if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
- break;
-
- udelay(2);
- } while (--timeout);
+ ret = readx_poll_timeout_atomic(axi_chan_irq_read, chan,
+ status, status & DWAXIDMAC_IRQ_SUSPENDED,
+ 2, 40);

axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);

@@ -1263,7 +1261,7 @@ static int dma_chan_pause(struct dma_chan *dchan)

spin_unlock_irqrestore(&chan->vc.lock, flags);

- return timeout ? 0 : -EAGAIN;
+ return ret ? -EAGAIN : 0;
}

/* Called in chan locked context */

--
2.53.0