From: sashiko-bot@kernel.org
To: "Rui Wang" <wr574332525@163.com>
Cc: Frank.Li@kernel.org, dmaengine@vger.kernel.org, vkoul@kernel.org
Subject: Re: [PATCH v2] dmaengine: dw-axi-dmac: report paused state and residue in tx_status
Date: Wed, 23 Sep 2026 03:58:31 +0000 [thread overview]
Message-ID: <20260923035831.947531F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260923034653.1413-1-wr574332525@163.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dmaengine: dw-axi-dmac: stale hardware pointer read causes false completion report
- [Medium] dmaengine: dw-axi-dmac: dma_chan_tx_status() fails to report DMA_PAUSED when txstate is NULL
--
commit 86d9aaad60c5959fbf2d93a893cc5a6deb51ce52
Author: Rui Wang <wr574332525@163.com>
dmaengine: dw-axi-dmac: report paused state and residue in tx_status
This commit updates the device_tx_status callback to report DMA_PAUSED
when a channel is paused. It also improves residue calculation for
in-flight transfers by reading the hardware CH_SAR/CH_DAR pointer and
walking the descriptor LLIs instead of relying on block-granular progress.
Link: https://lore.kernel.org/dmaengine/20260923030201.859-1-wr574332525@163.com/
> 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 eebed2474210d..2475ff7875537 100644
> --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
> +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
[ ... ]
> @@ -352,19 +352,73 @@ static void vchan_desc_put(struct virt_dma_desc *vdesc)
[ ... ]
> +static u32 axi_chan_get_xferred(struct axi_dma_chan *chan,
> + struct axi_dma_desc *desc)
> +{
> + struct axi_dma_hw_desc *hw_desc;
> + bool dst = chan->direction == DMA_DEV_TO_MEM;
> + u64 pos, start;
> + u32 xferred = 0;
> + int i;
> +
> + pos = axi_chan_readq(chan, dst ? CH_DAR : CH_SAR);
> +
> + for (i = 0; i < desc->nr_hw_descs; i++) {
> + hw_desc = &desc->hw_desc[i];
> + start = le64_to_cpu(dst ? hw_desc->lli->dar : hw_desc->lli->sar);
> +
> + /* Current position is inside this block: partial progress */
> + if (pos >= start && pos <= start + hw_desc->len)
> + return xferred + (u32)(pos - start);
> +
> + xferred += hw_desc->len;
> + }
> +
> + /* Position doesn't match any block, be conservative */
> + return 0;
> +}
> +
> static enum dma_status
> dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
> struct dma_tx_state *txstate)
> {
> struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
> struct virt_dma_desc *vdesc;
> + struct axi_dma_desc *desc;
> enum dma_status status;
> u32 completed_length;
> unsigned long flags;
> - u32 completed_blocks;
> size_t bytes = 0;
> u32 length;
> - u32 len;
>
> status = dma_cookie_status(dchan, cookie, txstate);
> if (status == DMA_COMPLETE || !txstate)
> return status;
[Severity: Medium]
Will clients querying the channel status without passing a dma_tx_state
struct receive DMA_IN_PROGRESS instead of the newly added DMA_PAUSED state?
If a client driver calls dmaengine_tx_status(chan, cookie, NULL) on a
paused channel, this early return skips the DMA_PAUSED check added at
the end of this function.
>
> @@ -374,13 +428,30 @@ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
>
> vdesc = vchan_find_desc(&chan->vc, cookie);
> if (vdesc) {
> - length = vd_to_axi_desc(vdesc)->length;
> - completed_blocks = vd_to_axi_desc(vdesc)->completed_blocks;
> - len = vd_to_axi_desc(vdesc)->hw_desc[0].len;
> - completed_length = completed_blocks * len;
> - bytes = length - completed_length;
> + desc = vd_to_axi_desc(vdesc);
> + length = desc->length;
> +
> + if (chan->cyclic)
> + completed_length = desc->completed_blocks *
> + desc->hw_desc[0].len;
> + else if (vdesc == vchan_next_desc(&chan->vc))
> + /*
> + * The descriptor is on the hardware: read the progress
> + * from its pointer. If the transfer has just finished
> + * but the interrupt has not reaped the descriptor yet,
> + * the pointer sits at the end and the residue reads 0.
> + */
> + completed_length = axi_chan_get_xferred(chan, desc);
[Severity: High]
Could this logic falsely report a zero residue (full completion) for a
newly submitted transfer before the hardware has actually started it?
If a transfer completes (leaving SAR/DAR pointing to the end of the
buffer) and a new transfer is submitted reusing the same memory buffer,
it becomes the active descriptor in vchan_next_desc.
If dma_chan_tx_status() is called before the DMA controller fetches the
first LLI and overwrites SAR/DAR, axi_chan_get_xferred() might read the
stale register value.
Because the buffer is reused, the stale position can fall into the new
descriptor's block range, causing the driver to conservatively compute
that all bytes have been transferred.
> + else
> + /* Still queued, nothing transferred yet */
> + completed_length = 0;
> +
> + bytes = length - min_t(u32, completed_length, length);
> }
>
> + if (chan->is_paused && status == DMA_IN_PROGRESS)
> + status = DMA_PAUSED;
> +
> spin_unlock_irqrestore(&chan->vc.lock, flags);
> dma_set_residue(txstate, bytes);
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260923034653.1413-1-wr574332525@163.com?part=1
prev parent reply other threads:[~2026-09-23 3:58 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 3:46 [PATCH v2] dmaengine: dw-axi-dmac: report paused state and residue in tx_status Rui Wang
2026-09-23 3:58 ` sashiko-bot [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=20260923035831.947531F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vkoul@kernel.org \
--cc=wr574332525@163.com \
/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