From: Frank Li <Frank.li@oss.nxp.com>
To: sashiko-reviews@lists.linux.dev
Cc: CL Wang <cl634@andestech.com>,
conor+dt@kernel.org, devicetree@vger.kernel.org,
dmaengine@vger.kernel.org, robh@kernel.org, vkoul@kernel.org,
Frank.Li@kernel.org
Subject: Re: [PATCH v8 2/2] dmaengine: atcdmac300: Add driver for Andes ATCDMAC300 DMA controller
Date: Thu, 1 Oct 2026 15:58:13 -0400 [thread overview]
Message-ID: <ar67VelbKVtiiCo6@lizhi-Precision-Tower-5810> (raw)
In-Reply-To: <20261001022703.73EFF1F000FF@smtp.kernel.org>
On Thu, Oct 01, 2026 at 02:27:02AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 11 potential issue(s) to consider:
> - [High] dmaengine: atcdmac300: missing interrupt enable flags in channel control
> - [High] dmaengine: atcdmac300: start unissued pending transfers in atcdmac_resume()
> - [High] dmaengine: atcdmac300: integer overflow of cyclic period variable
> - [High] dmaengine: atcdmac300: missing status clearing in atcdmac_terminate_all()
> - [High] dmaengine: atcdmac300: fail to reset chan_used flag during suspend
> - [High] dmaengine: atcdmac300: unhandled pending interrupt causes IRQ storm
> - [Medium] dmaengine: atcdmac300: ignore client transfer flags in atcdmac_prep_dma_memcpy()
> - [Medium] dmaengine: atcdmac300: memory leak of unsubmitted descriptors
> - [Medium] dmaengine: atcdmac300: integer truncation of len in atcdmac_prep_dma_memcpy()
> - [Medium] dmaengine: atcdmac300: integer truncation of sizes in atcdmac_prep_dma_cyclic()
> - [Medium] dmaengine: atcdmac300: missing args_count check in atcdmac_dma_xlate_handler()
> --
You should fix these issues for new drivers.
Frank
>
> commit 0b5c5b75d701997e0656ae1d35e0499a595165ad
> Author: CL Wang <cl634@andestech.com>
>
> dmaengine: atcdmac300: Add driver for Andes ATCDMAC300 DMA controller
>
> This patch adds support for the Andes ATCDMAC300 DMA controller.
> The ATCDMAC300 is a memory-to-memory and peripheral DMA controller
> that provides scatter-gather, cyclic, and slave transfer capabilities.
>
> > --- /dev/null
> > +++ b/drivers/dma/atcdmac300.c
> > @@ -0,0 +1,1759 @@
> [ ... ]
> > +static void atcdmac_start_transfer(struct atcdmac_chan *dmac_chan,
> > + struct atcdmac_desc *first_desc)
> > +{
> > + struct atcdmac_dmac *dmac = dmac_chan->dma_dev;
> > + struct regmap *reg = dmac_chan->regmap;
> > + unsigned long flags;
> > +
> > + raw_spin_lock_irqsave(&dmac->lock, flags);
> > + dmac->owned_chan |= BIT(dmac_chan->chan_id);
> > + raw_spin_unlock_irqrestore(&dmac->lock, flags);
> > +
> > + regmap_write(reg, REG_CH_CTL_OFF, first_desc->regs.ctrl);
>
> [Severity: High]
> Since INT_TC_MASK, INT_ERR_MASK, and INT_ABT_MASK are missing from the ctrl
> bitmask written here (and constructed in functions like
> atcdmac_build_slave_desc()), won't the hardware fail to assert interrupts
> upon completion, error, or abort? This appears to cause silent transfer
> timeouts.
>
> [ ... ]
> > +static void atcdmac_advance_work(struct atcdmac_chan *dmac_chan)
> > +{
> [ ... ]
> > + if (dma_desc->cyclic) {
> > + if (!stop)
> > + atcdmac_start_next_trans(dmac_chan);
> [ ... ]
> > + } else {
> > + if (list_is_singular(&dmac_chan->active_list)) {
> [ ... ]
> > + if (!stop)
> > + atcdmac_start_next_trans(dmac_chan);
>
> [Severity: High]
> If stop_mask is active during atcdmac_suspend(), this code skips calling
> atcdmac_start_next_trans(), which bypasses the internal reset of chan_used
> back to 0. Does this leave chan_used permanently stuck at 1?
>
> [ ... ]
> > +static int atcdmac_terminate_all(struct dma_chan *chan)
> > +{
> [ ... ]
> > + spin_lock_irqsave(&dmac_chan->lock, flags);
> > + atcdmac_abort_chan(dmac_chan);
> > + atcdmac_enable_chan(dmac_chan, 0);
> > + list_splice_init(&dmac_chan->queue_list, &list);
> > + list_splice_init(&dmac_chan->active_list, &list);
> > + dmac_chan->chan_used = 0;
> > + spin_unlock_irqrestore(&dmac_chan->lock, flags);
>
> [Severity: High]
> Does this code fail to clear the software state dmac_chan->status before
> dropping the lock? If an asynchronous abort interrupt fires as the channel
> is terminated, the threaded handler may process a stale ATCDMAC_STA_TC bit.
> If a client immediately queues and issues a new transfer, could
> atcdmac_advance_work() prematurely complete it?
>
> [ ... ]
> > +static void atcdmac_free_chan_resources(struct dma_chan *chan)
> > +{
> [ ... ]
> > + atcdmac_terminate_all(chan);
> > +
> > + /*
> > + * Give up ownership only after the abort raised by the termination
> > + * above has been serviced. Dropping the bit first would mask that
> > + * status out of the acknowledge and leave the interrupt asserted.
> > + */
> > + atcdmac_synchronize(chan);
> > +
> > + raw_spin_lock_irq(&dmac->lock);
> > + dmac->owned_chan &= ~BIT(dmac_chan->chan_id);
> > + raw_spin_unlock_irq(&dmac->lock);
>
> [Severity: High]
> Since atcdmac_synchronize() only flushes executing handlers and not pending
> hardware interrupts, does clearing owned_chan immediately afterward mask
> out a pending ABORT interrupt in the top-half handler? It seems this would
> leave the level-triggered interrupt line permanently asserted, causing an
> IRQ storm.
>
> > +
> > + spin_lock_irqsave(&dmac_chan->lock, flags);
> > + list_for_each_entry_safe(desc,
> > + desc_next,
> > + &dmac_chan->free_list,
> > + desc_node) {
> > + list_del(&desc->desc_node);
> > + dma_pool_free(dmac->dma_desc_pool, desc, desc->txd.phys);
> > + }
>
> [Severity: Medium]
> In the cleanup loop above, unsubmitted descriptors that were allocated but
> never submitted via dmaengine_submit() are unlinked from tracking lists.
> Will these unsubmitted descriptors leak since this loop only reclaims from
> free_list?
>
> [ ... ]
> > +static struct dma_async_tx_descriptor *
> > +atcdmac_prep_dma_memcpy(struct dma_chan *chan,
> > + dma_addr_t dst,
> > + dma_addr_t src,
> > + size_t len,
> > + unsigned long flags)
> > +{
> [ ... ]
> > + desc = atcdmac_build_desc(dmac_chan, src, dst, ctrl,
> > + len >> src_width);
>
> [Severity: Medium]
> When len is a 64-bit size_t value exceeding 4GB, does shifting it by
> src_width and passing it as a 32-bit unsigned int to atcdmac_build_desc()
> cause silent integer truncation, resulting in a partial transfer?
>
> > + if (!desc)
> > + goto err_desc_get;
> > +
> > + return &desc->txd;
>
> [Severity: Medium]
> Is there a missing assignment for the client transfer flags? The flags
> parameter is never assigned to desc->txd.flags, which ignores client
> intents like DMA_PREP_INTERRUPT or DMA_CTRL_REUSE.
>
> [ ... ]
> > +static struct dma_async_tx_descriptor *
> > +atcdmac_prep_dma_cyclic(struct dma_chan *chan,
> > + dma_addr_t buf_addr,
> > + size_t buf_len,
> > + size_t period_len,
> > + enum dma_transfer_direction direction,
> > + unsigned long flags)
> > +{
> [ ... ]
> > + unsigned int period;
> [ ... ]
> > + for (period = 0; period < buf_len; period += period_len) {
> > + struct atcdmac_desc *desc;
> > + dma_addr_t mem = buf_addr + period;
> > + unsigned int len = min_t(unsigned int, period_len,
> > + buf_len - period);
>
> [Severity: High]
> Since buf_len is a 64-bit size_t, does using a 32-bit unsigned int period
> cause an integer overflow for buffer lengths exceeding 4GB? This appears
> to create an infinite loop of descriptor allocations until the pool is
> exhausted.
>
> [Severity: Medium]
> Does the use of min_t(unsigned int, period_len, buf_len - period) silently
> truncate 64-bit size_t sizes over 4GB, programming a malformed transfer
> size?
>
> [ ... ]
> > +static struct dma_chan *atcdmac_dma_xlate_handler(struct of_phandle_args *dmac,
> > + struct of_dma *of_dma)
> > +{
> > + struct platform_device *dmac_pdev;
> > + struct atcdmac_chan *dmac_chan;
> > + struct dma_chan *chan;
> > + dma_cap_mask_t mask;
> > +
> > + if (dmac->args[0] > FIELD_MAX(SRC_REQ_SEL_MASK)) {
>
> [Severity: Medium]
> Does this code access dmac->args[0] without first verifying
> dmac->args_count? If #dma-cells = <0>, this may read uninitialized or
> out-of-bounds memory.
>
> [ ... ]
> > +static int atcdmac_resume(struct device *dev)
> > +{
> [ ... ]
> > + list_for_each_entry_safe(chan,
> > + chan_next,
> > + &dmac->dma_device.channels,
> > + device_node) {
> > + dmac_chan = atcdmac_chan_to_dmac_chan(chan);
> > + spin_lock_irqsave(&dmac_chan->lock, flags);
> > + if (!list_empty(&dmac_chan->active_list) ||
> > + !list_empty(&dmac_chan->queue_list))
> > + atcdmac_start_next_trans(dmac_chan);
> > + spin_unlock_irqrestore(&dmac_chan->lock, flags);
> > + }
>
> [Severity: High]
> If a client has queued descriptors but not yet called
> dma_async_issue_pending() (leaving chan_used == 0), does unconditionally
> starting the next transaction from queue_list violate the API contract by
> starting pending transfers prematurely?
>
> [Severity: High]
> Additionally, if both active_list and queue_list are empty, this bypasses
> atcdmac_start_next_trans(). Coupled with the issue in
> atcdmac_advance_work() above, does this solidify the leaked chan_used == 1
> state from suspend, permanently locking out the channel?
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261001014503.786490-1-cl634@andestech.com?part=2
next prev parent reply other threads:[~2026-10-01 19:58 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 1:45 [PATCH v8 0/2] dmaengine: atcdmac300: Add Andes ATCDMAC300 DMA driver CL Wang
2026-10-01 1:45 ` [PATCH v8 1/2] dt-bindings: dmaengine: Add support for ATCDMAC300 DMA engine CL Wang
2026-10-01 19:57 ` Frank Li
2026-10-01 21:12 ` Conor Dooley
2026-10-01 1:45 ` [PATCH v8 2/2] dmaengine: atcdmac300: Add driver for Andes ATCDMAC300 DMA controller CL Wang
2026-10-01 2:27 ` sashiko-bot
2026-10-01 19:58 ` Frank Li [this message]
2026-10-01 20:18 ` 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=ar67VelbKVtiiCo6@lizhi-Precision-Tower-5810 \
--to=frank.li@oss.nxp.com \
--cc=Frank.Li@kernel.org \
--cc=cl634@andestech.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=robh@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox