From: sashiko-bot@kernel.org
To: "Koichiro Den" <den@valinux.co.jp>
Cc: vkoul@kernel.org, Frank.Li@kernel.org, dmaengine@vger.kernel.org
Subject: Re: [PATCH 4/7] dmaengine: dw-edma: Serialize channel state checks
Date: Fri, 10 Jul 2026 08:28:29 +0000 [thread overview]
Message-ID: <20260710082829.EBBED1F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260710080903.2392888-5-den@valinux.co.jp>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Resuming a channel paused on the final chunk of a descriptor causes a permanent deadlock due to bypassed descriptor completion.
- [High] Race condition in `dw_edma_abort_interrupt` updating state outside of `vc.lock`
- [High] `dw_edma_device_terminate_all()` fails to reset `chan->request`, permanently wedging the channel on false-busy or timeout.
--
--- Patch [4]: [PATCH 4/7] dmaengine: dw-edma: Serialize channel state checks ---
commit d1992615b101e2e305e248b8535efc7b3e2c9e5f
Author: Koichiro Den <den@valinux.co.jp>
dmaengine: dw-edma: Serialize channel state checks
pause() and resume() read and update channel state without holding vc.lock,
while the interrupt handlers update the same state under it. Take the same
lock around those state checks so that request, status, and configured stay
consistent.
> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index 1b493c104a5b1..5664421c6f15b 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
[ ... ]
> @@ -318,8 +321,10 @@ static int dw_edma_device_pause(struct dma_chan *dchan)
> static int dw_edma_device_resume(struct dma_chan *dchan)
> {
> struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> + unsigned long flags;
> int err = 0;
>
> + spin_lock_irqsave(&chan->vc.lock, flags);
> if (!chan->configured) {
> err = -EPERM;
> } else if (chan->status != EDMA_ST_PAUSE) {
> @@ -330,6 +335,7 @@ static int dw_edma_device_resume(struct dma_chan *dchan)
> chan->status = EDMA_ST_BUSY;
> dw_edma_start_transfer(chan);
> }
[Severity: Critical]
This is a pre-existing issue, but I wanted to point out a potential deadlock
when resuming a paused channel.
If a channel is paused exactly as the final chunk of a descriptor finishes,
the interrupt handler dw_edma_done_interrupt() bypasses the normal chunk
depletion check:
drivers/dma/dw-edma/dw-edma-core.c:dw_edma_done_interrupt() {
...
case EDMA_REQ_PAUSE:
chan->request = EDMA_REQ_NONE;
chan->status = EDMA_ST_PAUSE;
break;
...
}
This leaves the depleted descriptor in the issued queue. Later, when resume is
called, dw_edma_start_transfer() attempts to start this empty descriptor,
finds no chunks, and returns 0.
However, dw_edma_device_resume() ignores this return value and unconditionally
sets chan->status = EDMA_ST_BUSY. Would this result in the hardware never
starting and the channel remaining irreversibly stuck in the EDMA_ST_BUSY
state?
> + spin_unlock_irqrestore(&chan->vc.lock, flags);
>
> return err;
> }
While looking at the state locking changes in this patch, I noticed a couple
of other pre-existing issues in this file related to state transitions:
[Severity: High]
This isn't a bug introduced by this patch, but does dw_edma_abort_interrupt()
have a similar race condition to the ones being fixed here?
drivers/dma/dw-edma/dw-edma-core.c:dw_edma_abort_interrupt() {
...
spin_lock_irqsave(&chan->vc.lock, flags);
vd = vchan_next_desc(&chan->vc);
if (vd) {
dw_hdma_set_callback_result(vd, DMA_TRANS_ABORTED);
list_del(&vd->node);
vchan_cookie_complete(vd);
}
spin_unlock_irqrestore(&chan->vc.lock, flags);
chan->request = EDMA_REQ_NONE;
chan->status = EDMA_ST_IDLE;
}
The lock is dropped before updating chan->request and chan->status.
If dw_edma_device_issue_pending() executes on another CPU in this unprotected
window, it could acquire vc.lock, observe a stale EDMA_ST_BUSY state, and
correctly skip starting the hardware for newly queued descriptors. Once
dw_edma_abort_interrupt() resumes and sets the state to EDMA_ST_IDLE, would
the engine remain stopped, leaving the new descriptors stranded forever?
[Severity: High]
This is also a pre-existing issue, but does dw_edma_device_terminate_all()
need to clear chan->request in its error paths?
drivers/dma/dw-edma/dw-edma-core.c:dw_edma_device_terminate_all() {
...
} else if (dw_edma_core_ch_status(chan) == DMA_COMPLETE) {
/*
* The channel is in a false BUSY state, probably didn't
* receive or lost an interrupt
*/
dw_edma_terminate_all_descs(chan);
chan->status = EDMA_ST_IDLE;
chan->configured = false;
}
...
}
If a channel is paused (chan->request == EDMA_REQ_PAUSE) and the transfer
finished in hardware but the interrupt was lost, it seems we take this branch
and set chan->status = EDMA_ST_IDLE without clearing chan->request.
Since future calls to dw_edma_device_issue_pending() require chan->request ==
EDMA_REQ_NONE, would this stale request state persist and indefinitely wedge
the channel?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260710080903.2392888-1-den@valinux.co.jp?part=4
next prev parent reply other threads:[~2026-07-10 8:28 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 8:08 [PATCH 0/7] dmaengine: dw-edma: Fixes and interrupt-path groundwork Koichiro Den
2026-07-10 8:08 ` [PATCH 1/7] dmaengine: dw-edma: Fix HDMA channel status register access Koichiro Den
2026-07-10 8:19 ` sashiko-bot
2026-07-10 21:26 ` Frank Li
2026-07-13 5:17 ` Koichiro Den
2026-07-10 8:08 ` [PATCH 2/7] dmaengine: dw-edma: Terminate STOP requests without callbacks Koichiro Den
2026-07-10 8:26 ` sashiko-bot
2026-07-11 14:27 ` Frank Li
2026-07-10 8:08 ` [PATCH 3/7] dmaengine: dw-edma: Clean up vchan descriptors on termination Koichiro Den
2026-07-10 8:24 ` sashiko-bot
2026-07-11 14:39 ` Frank Li
2026-07-10 8:09 ` [PATCH 4/7] dmaengine: dw-edma: Serialize channel state checks Koichiro Den
2026-07-10 8:28 ` sashiko-bot [this message]
2026-07-10 8:09 ` [PATCH 5/7] dmaengine: dw-edma-pcie: Drop redundant pci_free_irq_vectors() Koichiro Den
2026-07-11 14:41 ` Frank Li
2026-07-10 8:09 ` [PATCH 6/7] dmaengine: dw-edma: Snapshot the v0 interrupt status once per handler pass Koichiro Den
2026-07-11 14:44 ` Frank Li
2026-07-10 8:09 ` [PATCH 7/7] dmaengine: dw-edma: Defer channel IRQ handling to workqueue Koichiro Den
2026-07-10 8:24 ` sashiko-bot
2026-07-11 14:55 ` Frank Li
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=20260710082829.EBBED1F00A3D@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=den@valinux.co.jp \
--cc=dmaengine@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.