All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Hongling Zeng" <zenghongling@kylinos.cn>
Cc: Frank.Li@kernel.org, vkoul@kernel.org,
	linux-sunxi@lists.linux.dev, dmaengine@vger.kernel.org
Subject: Re: [PATCH] dmaengine: sun6i: Fix potential deadlock in dma_terminate_all and pause
Date: Sun, 05 Jul 2026 08:31:33 +0000	[thread overview]
Message-ID: <20260705083134.001491F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260705082105.13325-1-zenghongling@kylinos.cn>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] Use of spin_lock_irq()/spin_unlock_irq() unconditionally re-enables hardware interrupts, breaking caller atomic contexts.

Pre-existing issues:
- [High] Lockless reads of vchan->phy introduce Time-of-Check to Time-of-Use (TOCTOU) races causing cross-channel interference.
- [High] Active, non-cyclic DMA descriptors are leaked upon channel termination.
--

commit 5ad36fe6cb5ac09d034a98b6efc7e6a3152d1705
Author: Hongling Zeng <zenghongling@kylinos.cn>

dmaengine: sun6i: Fix potential deadlock in dma_terminate_all and pause

This patch addresses a deadlock between process context and the DMA tasklet
in softirq context. It replaces plain spin_lock() and spin_unlock() with
their irq variants for sdev->lock in sun6i_dma_pause() and
sun6i_dma_terminate_all().

> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index a9a254dbf8cb9..37b143a8f75e2 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -898,9 +898,9 @@ static int sun6i_dma_pause(struct dma_chan *chan)
>  		writel(DMA_CHAN_PAUSE_PAUSE,
>  		       pchan->base + DMA_CHAN_PAUSE);
>  	} else {
> -		spin_lock(&sdev->lock);
> +		spin_lock_irq(&sdev->lock);
>  		list_del_init(&vchan->node);
> -		spin_unlock(&sdev->lock);
> +		spin_unlock_irq(&sdev->lock);

[Severity: High]
Does spin_unlock_irq() unintentionally enable hardware interrupts for callers
that enter this function with interrupts disabled?

DMA engine API functions like dmaengine_pause() are frequently called by
client drivers from atomic contexts where interrupts are already disabled (for
example, while holding a lock via spin_lock_irqsave()). Since
spin_unlock_irq() unconditionally re-enables hardware interrupts, could this
destroy the caller's atomicity and lead to scheduling while atomic panics or
deadlocks?

Would it be safer to use spin_lock_irqsave() and spin_unlock_irqrestore()
here instead?

[ ... ]

> @@ -939,9 +939,9 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
>  	unsigned long flags;
>  	LIST_HEAD(head);

[Severity: High]
This is a pre-existing issue, but does fetching the physical channel pointer
locklessly at the start of this function introduce a race condition?

At the top of sun6i_dma_terminate_all(), we have:

    struct sun6i_pchan *pchan = vchan->phy;

If a DMA transfer completes concurrently on another CPU, the tasklet might
clear vchan->phy and reassign the same pchan to a different virtual channel.
When sun6i_dma_terminate_all() later acquires the lock and calls writel() to
stop the channel, could it mistakenly stop an unrelated transfer that was just
started on that physical channel?

[Severity: High]
This is a pre-existing issue, but does sun6i_dma_terminate_all() leak active
non-cyclic descriptors?

When terminating, the function has logic to rescue cyclic descriptors and move
them to the completed list:

    if (vchan->cyclic) {
        vchan->cyclic = false;
        if (pchan && pchan->desc) {
            ...
            list_add_tail(&vd->node, &vc->desc_completed);
        }
    }

However, for non-cyclic transfers, it ignores the active descriptor entirely
and sets pchan->desc = NULL. Because vchan_get_all_descriptors() only grabs
descriptors from the tracking lists, the active non-cyclic descriptor is
bypassed and lost. Could this lead to a permanent memory leak of sun6i_desc
structures and their associated hardware pools when non-cyclic transfers are
aborted?

> -	spin_lock(&sdev->lock);
> +	spin_lock_irq(&sdev->lock);
>  	list_del_init(&vchan->node);
> -	spin_unlock(&sdev->lock);
> +	spin_unlock_irq(&sdev->lock);

[Severity: High]
Similar to sun6i_dma_pause(), will this spin_unlock_irq() unconditionally
enable hardware interrupts and break the caller's atomic context?

Also, because it re-enables interrupts before the immediately following
spin_lock_irqsave(&vchan->vc.lock, flags) call, could it corrupt the IRQ
state saved in flags?

>  
>  	spin_lock_irqsave(&vchan->vc.lock, flags);
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260705082105.13325-1-zenghongling@kylinos.cn?part=1

      reply	other threads:[~2026-07-05  8:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-05  8:21 [PATCH] dmaengine: sun6i: Fix potential deadlock in dma_terminate_all and pause Hongling Zeng
2026-07-05  8:31 ` 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=20260705083134.001491F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-sunxi@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    --cc=zenghongling@kylinos.cn \
    /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.