From: sashiko-bot@kernel.org
To: "Rosen Penev" <rosenp@gmail.com>
Cc: vkoul@kernel.org, Frank.Li@kernel.org, dmaengine@vger.kernel.org
Subject: Re: [PATCH] dmaengine: fsl_raid: fix 64-bit ring base address programming
Date: Thu, 10 Sep 2026 20:33:39 +0000 [thread overview]
Message-ID: <20260910203340.705B11F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260910201717.44891-1-rosenp@gmail.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [High] The return value of fsl_re_chan_probe() is ignored, leading to a NULL pointer dereference on driver removal.
- [High] The driver calls request_irq() without a corresponding free_irq(), causing a Use-After-Free panic on module removal.
- [High] Channels are never added to the DMA device's channel list, resulting in a non-functional driver.
- [High] The interrupt handler is registered before critical driver data is initialized, leading to crashes from early interrupts.
- [High] The driver invokes the DMA client completion callback while holding desc_lock, causing an AB-BA self-deadlock if the client submits a new transaction.
- [High] fsl_re_free_chan_resources() modifies the free_q list without holding desc_lock and improperly loops based on alloc_count.
--
commit ac27e4641c6966f6e1eb9d43776e03a8a1dcc825
Author: Rosen Penev <rosenp@gmail.com>
dmaengine: fsl_raid: fix 64-bit ring base address programming
The driver claims a 40-bit DMA mask via dma_set_mask(40), but the
inbound/outbound ring base addresses were programmed by masking the
physical address with FSL_RE_ADDR_BIT_MASK (0xF) into the high register
and shifting it right by FSL_RE_ADDR_BIT_SHIFT (4) into the low register.
> diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
> index 2d86f61105e52..e8223ac38e222 100644
> --- a/drivers/dma/fsl_raid.c
> +++ b/drivers/dma/fsl_raid.c
> @@ -707,15 +707,19 @@ static int fsl_re_chan_probe(struct platform_device *ofdev,
> goto err_free_1;
> }
>
> - /* Program the Inbound/Outbound ring base addresses and size */
> + /* Program the Inbound/Outbound ring base addresses and size.
> + * The DMA rings are 64-bit addresses split into high/low registers.
> + * The driver supports a 40-bit DMA mask, so the low register holds
> + * bits [31:0] and the high register holds bits [39:32].
> + */
> out_be32(&chan->jrregs->inbring_base_h,
> - chan->inb_phys_addr & FSL_RE_ADDR_BIT_MASK);
> + upper_32_bits(chan->inb_phys_addr) & FSL_RE_ADDR_HIGH_MASK);
> out_be32(&chan->jrregs->oubring_base_h,
> - chan->oub_phys_addr & FSL_RE_ADDR_BIT_MASK);
> + upper_32_bits(chan->oub_phys_addr) & FSL_RE_ADDR_HIGH_MASK);
> out_be32(&chan->jrregs->inbring_base_l,
> - chan->inb_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> + lower_32_bits(chan->inb_phys_addr));
> out_be32(&chan->jrregs->oubring_base_l,
> - chan->oub_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> + lower_32_bits(chan->oub_phys_addr));
> out_be32(&chan->jrregs->inbring_size,
> FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
> out_be32(&chan->jrregs->oubring_size,
> diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
> index adbfede330a77..748047996bbcc 100644
> --- a/drivers/dma/fsl_raid.h
> +++ b/drivers/dma/fsl_raid.h
> @@ -66,8 +66,7 @@
> #define FSL_RE_RING_SIZE 0x400
> #define FSL_RE_RING_SIZE_MASK (FSL_RE_RING_SIZE - 1)
> #define FSL_RE_RING_SIZE_SHIFT 8
> -#define FSL_RE_ADDR_BIT_SHIFT 4
> -#define FSL_RE_ADDR_BIT_MASK (BIT(FSL_RE_ADDR_BIT_SHIFT) - 1)
> +#define FSL_RE_ADDR_HIGH_MASK 0xFF
> #define FSL_RE_ERROR 0x40000000
> #define FSL_RE_INTR 0x80000000
> #define FSL_RE_CLR_INTR 0x80000000
[Severity: High]
This is a pre-existing issue, but I noticed the return value of
fsl_re_chan_probe() is ignored, which can lead to a NULL pointer dereference
on driver removal.
drivers/dma/fsl_raid.c:fsl_re_probe() {
...
if (rc) {
fsl_re_chan_probe(ofdev, child, ridx++, off);
re_priv->total_chans++;
}
...
}
If fsl_re_chan_probe() fails, re_priv->total_chans is still incremented,
and re_priv->re_jrs[q] remains NULL. During teardown, fsl_re_remove() calls
fsl_re_remove_chan() which unconditionally dereferences it:
drivers/dma/fsl_raid.c:fsl_re_remove_chan() {
tasklet_kill(&chan->irqtask);
...
}
Will this cause a kernel panic on driver unbind if any channel failed to
probe?
[Severity: High]
This isn't a bug introduced by this patch, but I noticed request_irq() is
called without a corresponding free_irq(), which can cause a use-after-free
panic on module removal.
drivers/dma/fsl_raid.c:fsl_re_chan_probe() {
...
ret = request_irq(chan->irq, fsl_re_isr, 0, chan->name, chandev);
if (ret) {
...
err_free:
return ret;
}
The interrupt handler doesn't appear to be freed in error paths or during
teardown in fsl_re_remove_chan():
drivers/dma/fsl_raid.c:fsl_re_remove_chan() {
tasklet_kill(&chan->irqtask);
dma_pool_free(chan->re_dev->hw_desc_pool, chan->inb_ring_virt_addr,
chan->inb_phys_addr);
...
}
If a hardware interrupt fires after the module is unloaded, will the kernel
jump into freed module memory?
[Severity: High]
This is a pre-existing issue, but it looks like channels are never added to
the DMA device's channel list, which might result in a non-functional driver.
drivers/dma/fsl_raid.c:fsl_re_chan_probe() {
...
re_priv->re_jrs[q] = chan;
chan->chan.device = dma_dev;
chan->chan.private = chan;
chan->dev = chandev;
...
}
The global channel list is initialized via INIT_LIST_HEAD(&dma_dev->channels),
but list_add_tail(&chan->chan.device_node, &dma_dev->channels) is never
called. Will dma_async_device_register() iterate over an empty list and
register zero channels?
[Severity: High]
This isn't a bug introduced by this patch, but the interrupt handler is
registered before critical driver data is initialized, which could lead to
crashes from early interrupts.
drivers/dma/fsl_raid.c:fsl_re_chan_probe() {
...
ret = request_irq(chan->irq, fsl_re_isr, 0, chan->name, chandev);
...
dev_set_drvdata(chandev, chan);
...
}
If a spurious or early interrupt triggers immediately after request_irq(),
the ISR will execute dev_get_drvdata() and receive NULL:
drivers/dma/fsl_raid.c:fsl_re_isr() {
...
re_chan = dev_get_drvdata((struct device *)data);
irqstate = in_be32(&re_chan->jrregs->jr_interrupt_status);
...
}
Could this cause a NULL pointer dereference panic while reading
jr_interrupt_status?
[Severity: High]
This is a pre-existing issue, but the driver invokes the DMA client completion
callback while holding desc_lock, which can cause an AB-BA self-deadlock.
drivers/dma/fsl_raid.c:fsl_re_dequeue() {
...
spin_lock_irqsave(&re_chan->desc_lock, flags);
...
if (found) {
fsl_re_desc_done(desc);
...
}
If the client submits a chained DMA request within the callback,
fsl_re_tx_submit() attempts to re-acquire the exact same desc_lock:
drivers/dma/fsl_raid.c:fsl_re_tx_submit() {
...
spin_lock_irqsave(&re_chan->desc_lock, flags);
...
}
Will this instantly deadlock the CPU?
[Severity: High]
This isn't a bug introduced by this patch, but fsl_re_free_chan_resources()
modifies the free_q list without holding desc_lock and improperly loops based
on alloc_count.
drivers/dma/fsl_raid.c:fsl_re_free_chan_resources() {
...
while (re_chan->alloc_count--) {
desc = list_first_entry(&re_chan->free_q,
struct fsl_re_desc,
node);
list_del(&desc->node);
...
kfree(desc);
}
}
If any descriptors are still in flight, free_q will be prematurely empty,
causing list_first_entry() to return an invalid pointer which is then freed.
Should this be protected by desc_lock and use list_empty() checks?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910201717.44891-1-rosenp@gmail.com?part=1
next prev parent reply other threads:[~2026-09-10 20:33 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 20:17 [PATCH] dmaengine: fsl_raid: fix 64-bit ring base address programming Rosen Penev
2026-09-10 20:33 ` sashiko-bot [this message]
2026-09-11 15:42 ` 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=20260910203340.705B11F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=rosenp@gmail.com \
--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.