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 2/3] dma: fsl_raid: keep MMIO bases as void __iomem and cast at access
Date: Tue, 14 Jul 2026 23:49:36 +0000 [thread overview]
Message-ID: <20260714234936.8E74D1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260714233855.870797-3-rosenp@gmail.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing return value check for `fsl_re_chan_probe()` causes NULL pointer dereference.
- [High] Race condition during probe causes NULL pointer dereference in the ISR.
- [High] Missing `free_irq()` causes Use-After-Free of the interrupt handler.
- [High] DMA channels are never added to the DMA device's channel list.
- [High] The driver invokes the client callback while holding the channel's spinlock, risking an ABBA deadlock.
--
--- Patch [2]: [PATCH 2/3] dma: fsl_raid: keep MMIO bases as void __iomem and cast at access ---
commit efbae01ecec4b10e7d40ae8af0275362e4f9669a
Author: Rosen Penev <rosenp@gmail.com>
dma: fsl_raid: keep MMIO bases as void __iomem and cast at access
This patch updates the driver to store MMIO bases as void __iomem pointers
and uses typed local pointers to access fields. This resolves sparse warnings
about different address spaces when using ioread32be() and iowrite32be().
Link: https://lore.kernel.org/oe-kbuild-all/202008111749.yy85rFMD%25lkp@intel.com/
> diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
> index 888f55b672a58..47ebdf2743310 100644
> --- a/drivers/dma/fsl_raid.c
> +++ b/drivers/dma/fsl_raid.c
[ ... ]
> @@ -167,7 +170,7 @@ static void fsl_re_dequeue(struct tasklet_struct *t)
> fsl_re_cleanup_descs(re_chan);
>
> spin_lock_irqsave(&re_chan->desc_lock, flags);
> - count = FSL_RE_SLOT_FULL(in_be32(&re_chan->jrregs->oubring_slot_full));
> + count = FSL_RE_SLOT_FULL(in_be32(&jr->oubring_slot_full));
[Severity: High]
This is a pre-existing issue, but can this lock handling cause a recursive
deadlock?
In fsl_re_dequeue(), desc_lock is acquired via spin_lock_irqsave(). While
iterating through completed descriptors, fsl_re_desc_done() is called:
while (count--) {
...
if (found) {
fsl_re_desc_done(desc);
list_move_tail(&desc->node, &re_chan->ack_q);
}
...
}
fsl_re_desc_done() invokes the client callback inline. If the client attempts
to submit new work from its callback, fsl_re_tx_submit() will attempt to
acquire the exact same desc_lock, resulting in a deadlock.
> while (count--) {
> found = 0;
> hwdesc = &re_chan->oub_ring_virt_addr[re_chan->oub_count];
[ ... ]
> @@ -201,12 +203,12 @@ static void fsl_re_dequeue(struct tasklet_struct *t)
> /* Per Job Ring interrupt handler */
> static irqreturn_t fsl_re_isr(int irq, void *data)
> {
> - struct fsl_re_chan *re_chan;
> + struct device *dev = data;
> + struct fsl_re_chan *re_chan = dev_get_drvdata(dev);
> + struct fsl_re_chan_cfg __iomem *jr = re_chan->jrregs;
[Severity: High]
This isn't a bug introduced by this patch, but does this assume drvdata is
already set when the interrupt fires?
In fsl_re_chan_probe(), request_irq() is called to register this handler
before dev_set_drvdata(chandev, chan) sets the driver data.
If an interrupt fires immediately after registration, dev_get_drvdata(dev)
will return NULL, leading to a crash when dereferencing re_chan->jrregs.
> u32 irqstate, status;
>
> - re_chan = dev_get_drvdata((struct device *)data);
> -
> - irqstate = in_be32(&re_chan->jrregs->jr_interrupt_status);
> + irqstate = in_be32(&jr->jr_interrupt_status);
> if (!irqstate)
> return IRQ_NONE;
>
[ ... ]
> @@ -709,30 +712,23 @@ static int fsl_re_chan_probe(struct platform_device *ofdev,
> }
>
> /* Program the Inbound/Outbound ring base addresses and size */
> - out_be32(&chan->jrregs->inbring_base_h,
> - chan->inb_phys_addr & FSL_RE_ADDR_BIT_MASK);
> - out_be32(&chan->jrregs->oubring_base_h,
> - chan->oub_phys_addr & FSL_RE_ADDR_BIT_MASK);
> - out_be32(&chan->jrregs->inbring_base_l,
> - chan->inb_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> - out_be32(&chan->jrregs->oubring_base_l,
> - chan->oub_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> - out_be32(&chan->jrregs->inbring_size,
> - FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
> - out_be32(&chan->jrregs->oubring_size,
> - FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
> + out_be32(&jr->inbring_base_h, chan->inb_phys_addr & FSL_RE_ADDR_BIT_MASK);
> + out_be32(&jr->oubring_base_h, chan->oub_phys_addr & FSL_RE_ADDR_BIT_MASK);
> + out_be32(&jr->inbring_base_l, chan->inb_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> + out_be32(&jr->oubring_base_l, chan->oub_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
> + out_be32(&jr->inbring_size, FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
> + out_be32(&jr->oubring_size, FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
>
> /* Read LIODN value from u-boot */
> - status = in_be32(&chan->jrregs->jr_config_1) & FSL_RE_REG_LIODN_MASK;
> + status = in_be32(&jr->jr_config_1) & FSL_RE_REG_LIODN_MASK;
>
> /* Program the CFG reg */
> - out_be32(&chan->jrregs->jr_config_1,
> - FSL_RE_CFG1_CBSI | FSL_RE_CFG1_CBS0 | status);
> + out_be32(&jr->jr_config_1, FSL_RE_CFG1_CBSI | FSL_RE_CFG1_CBS0 | status);
>
> dev_set_drvdata(chandev, chan);
[Severity: High]
This is a pre-existing issue, but are we leaking the registered IRQ?
Neither the error path of fsl_re_chan_probe() nor the teardown function
fsl_re_remove_chan() appears to call free_irq().
If fsl_re_chan_probe() fails after request_irq(), or if the module is
unloaded, the ISR remains registered. This could lead to a use-after-free
if an interrupt fires and attempts to execute unmapped memory.
[Severity: High]
This is another pre-existing issue, but is it intentional that the
initialized DMA channel is not added to the DMA device's channel list?
Earlier in fsl_re_chan_probe(), the channel is initialized:
re_priv->re_jrs[q] = chan;
chan->chan.device = dma_dev;
...
However, list_add_tail(&chan->chan.device_node, &dma_dev->channels) is never
called. When dma_async_device_register() is executed, it might find the list
empty and register 0 channels, making them unavailable to clients.
>
> /* Enable RE/CHAN */
> - out_be32(&chan->jrregs->jr_command, FSL_RE_ENABLE);
> + out_be32(&jr->jr_command, FSL_RE_ENABLE);
>
> return 0;
>
[ ... ]
> @@ -752,6 +748,7 @@ static int fsl_re_probe(struct platform_device *ofdev)
> u8 ridx = 0;
> struct dma_device *dma_dev;
> struct resource *res;
> + struct fsl_re_ctrl __iomem *re_regs;
> int rc;
> struct device *dev = &ofdev->dev;
[Severity: High]
This is a pre-existing issue, but is it safe to ignore the return value of
fsl_re_chan_probe() later in this function?
If the probe fails (e.g. out of memory), total_chans is still incremented:
for_each_child_of_node(np, child) {
rc = of_device_is_compatible(child, "fsl,raideng-v1.0-job-ring");
if (rc) {
fsl_re_chan_probe(ofdev, child, ridx++, off);
re_priv->total_chans++;
}
}
This leaves an uninitialized pointer in the re_jrs array, which might be
dereferenced as a NULL pointer during driver unbind in fsl_re_remove_chan()
when it calls tasklet_kill(&chan->irqtask).
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260714233855.870797-1-rosenp@gmail.com?part=2
next prev parent reply other threads:[~2026-07-14 23:49 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 23:38 [PATCH 0/3] dma: fsl_raid: fix sparse warnings and simplify probing Rosen Penev
2026-07-14 23:38 ` [PATCH 1/3] dma: fsl_raid: fix endianness of in-memory descriptor stores Rosen Penev
2026-07-15 0:06 ` sashiko-bot
2026-07-14 23:38 ` [PATCH 2/3] dma: fsl_raid: keep MMIO bases as void __iomem and cast at access Rosen Penev
2026-07-14 23:49 ` sashiko-bot [this message]
2026-07-14 23:38 ` [PATCH 3/3] dma: fsl_raid: use devm_platform_ioremap_resource Rosen Penev
2026-07-14 23:50 ` sashiko-bot
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=20260714234936.8E74D1F000E9@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox