From: James Hilliard <james.hilliard1@gmail.com>
To: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>,
Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
Sergey Khimich <serghox@gmail.com>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Sia Jee Heng <jee.heng.sia@intel.com>
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
James Hilliard <james.hilliard1@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH 3/3] dmaengine: dw-axi-dmac: preserve suspension status until pause observes it
Date: Sun, 08 Nov 2026 22:02:38 -0700 [thread overview]
Message-ID: <20261108-submit-dw-axi-dma-stop-pause-v1-v1-3-c48ec19e9ee4@gmail.com> (raw)
In-Reply-To: <20261108-submit-dw-axi-dma-stop-pause-v1-v1-0-c48ec19e9ee4@gmail.com>
dma_chan_pause() clears SUSPENDED even when polling times out. Hardware
can set that status after the last poll, including during the final
delay, and the unconditional clear then discards an acknowledgment the
caller never observed. Another channel's interrupt can also consume the
status because the shared IRQ handler clears every channel's status
before taking its lock. Masking the suspend interrupt signal does not
prevent either path from clearing the status used by the polling code.
Leave SUSPENDED to the pause path and acknowledge it only after a
successful poll. A timed-out pause can then be retried without losing a
late acknowledgment. Mark the channel paused only after confirmation,
and let repeated pause calls succeed while it remains paused.
Clear the saved state and any old suspension status when enabling a
channel or completing termination, so a later transfer must obtain its
own acknowledgment. These state changes are serialized with pause by
the channel lock.
Fixes: 1fe20f1b8454 ("dmaengine: Introduce DW AXI DMAC driver")
Cc: stable@vger.kernel.org
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 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 de092f190528..33340f0e7462 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -226,6 +226,9 @@ static inline void axi_chan_enable(struct axi_dma_chan *chan)
{
u64 val;
+ axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);
+ chan->is_paused = false;
+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
if (chan->id >= DMAC_CHAN_16) {
@@ -1161,6 +1164,8 @@ static irqreturn_t dw_axi_dma_interrupt(int irq, void *dev_id)
for (i = 0; i < dw->hdata->nr_channels; i++) {
chan = &dw->chan[i];
status = axi_chan_irq_read(chan);
+ /* Suspension status is consumed by dma_chan_pause(). */
+ status &= ~DWAXIDMAC_IRQ_SUSPENDED;
axi_chan_irq_clear(chan, status);
dev_vdbg(chip->dev, "%s %u IRQ status: 0x%08x\n",
@@ -1206,6 +1211,8 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
vchan_get_all_descriptors(&chan->vc, &head);
+ axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);
+ chan->is_paused = false;
chan->cyclic = false;
spin_unlock_irqrestore(&chan->vc.lock, flags);
@@ -1225,6 +1232,9 @@ static int dma_chan_pause(struct dma_chan *dchan)
spin_lock_irqsave(&chan->vc.lock, flags);
+ if (chan->is_paused)
+ goto out;
+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
if (chan->id >= DMAC_CHAN_16) {
@@ -1258,10 +1268,12 @@ static int dma_chan_pause(struct dma_chan *dchan)
udelay(2);
} while (--timeout);
- axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);
-
- chan->is_paused = true;
+ if (timeout) {
+ axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);
+ chan->is_paused = true;
+ }
+out:
spin_unlock_irqrestore(&chan->vc.lock, flags);
return timeout ? 0 : -EAGAIN;
--
2.53.0
prev parent reply other threads:[~2026-11-09 5:02 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 5:02 [PATCH 0/3] dmaengine: dw-axi-dmac: fix termination and pause acknowledgment James Hilliard
2026-11-09 5:02 ` [PATCH 1/3] dmaengine: dw-axi-dmac: poll the correct enable bit during termination James Hilliard
2026-11-09 22:49 ` Andy Shevchenko
2026-11-09 5:02 ` [PATCH 2/3] dmaengine: dw-axi-dmac: retain descriptors when termination times out James Hilliard
2026-11-09 5:02 ` James Hilliard [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261108-submit-dw-axi-dma-stop-pause-v1-v1-3-c48ec19e9ee4@gmail.com \
--to=james.hilliard1@gmail.com \
--cc=Eugeniy.Paltsev@synopsys.com \
--cc=Frank.Li@kernel.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=dmaengine@vger.kernel.org \
--cc=jee.heng.sia@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=serghox@gmail.com \
--cc=stable@vger.kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®