All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "CL Wang" <cl634@andestech.com>
Cc: 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, 01 Oct 2026 02:27:02 +0000	[thread overview]
Message-ID: <20261001022703.73EFF1F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20261001014503.786490-3-cl634@andestech.com>

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()
--

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

  reply	other threads:[~2026-10-01  2:27 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 [this message]
2026-10-01 19:58     ` Frank Li
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=20261001022703.73EFF1F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --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 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.