Re: [PATCH v4 4/5] irqchip/imx-irqsteer: Mask all interrupts in probe()

Frank Li <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.imx
Message-ID <aoXAXFI3kRWh98R7@SMW015318>
On Wed, Aug 19, 2026 at 09:25:06AM +0000, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
>
> New issues:
> - [High] The patch introduces an unvalidated loop that performs out-of-bounds MMIO writes if an excessively large `fsl,num-irqs` value is provided.
>
> Pre-existing issues:
> - [High] Missing Runtime PM cleanup causes unbalanced clock disable and potential external abort on device unbind.
> - [High] Missing synchronization with chained parent IRQ handler in `remove()` leading to potential external abort.
> --
>
> --- Patch [4]: [PATCH v4 4/5] irqchip/imx-irqsteer: Mask all interrupts in probe() ---
> commit ecdadc89363972642c46a3ef5443dd52db1ecece
> Author: Zhipeng Wang <[email protected]>
>
> irqchip/imx-irqsteer: Mask all interrupts in probe()
>
> probe() sets up the chained handlers without first masking the input
> interrupts. Mask all interrupts in probe() before wiring up the chained
> handlers to prevent storms from stale asserted lines.
>
> > diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
> > index 320082d3a6325..a9909ecb6fef7 100644
> > --- a/drivers/irqchip/irq-imx-irqsteer.c
> > +++ b/drivers/irqchip/irq-imx-irqsteer.c
> > @@ -236,6 +236,14 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
> >  	if (irqsteer_has_chanctrl(data->devtype_data))
> >  		writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
> >
> > +	/*
> > +	 * Mask all interrupts before wiring up the chained handlers. CHANMASK
> > +	 * has inverted polarity (a set bit enables the interrupt), so writing
> > +	 * zero masks the source.
> > +	 */
> > +	for (i = 0; i < data->reg_num; i++)
> > +		writel_relaxed(0, data->regs + CHANMASK(i, data->reg_num));
> > +
>
> [Severity: High]
> Can this loop perform out-of-bounds MMIO writes?
>
> If a large value is provided for "fsl,num-irqs" in the device tree,
> data->reg_num could be oversized. The bounds check for the maximum
> number of interrupts happens later in the function:
>
> 	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
> 		ret = -EINVAL;
> 		goto out;
> 	}
>

Make sense, this check should just after

	data->irq_count = DIV_ROUND_UP(irqs_num, 64);
        data->reg_num = irqs_num / 32;

Frank

> Since this validation executes after the new loop, an oversized value
> would cause out-of-bounds writes to data->regs before being caught.
>
> Could the validation check be moved before this loop?
>
> [ ... ]
>
> While reviewing this file, I also noticed a couple of pre-existing issues in
> imx_irqsteer_remove().
>
> drivers/irqchip/irq-imx-irqsteer.c:imx_irqsteer_remove() {
> ...
> 	for (i = 0; i < irqsteer_data->irq_count; i++) {
> 		irq_set_chained_handler_and_data(irqsteer_data->irq[i],
> 						 NULL, NULL);
> 		irq_dispose_mapping(irqsteer_data->irq[i]);
> 	}
>
> 	clk_disable_unprepare(irqsteer_data->ipg_clk);
> ...
> }
>
> [Severity: High]
> This isn't a bug introduced by this patch, but can clearing the chained
> handler here race with an executing handler and cause an external abort?
>
> Chained handlers bypass desc->lock and do not set IRQS_INPROGRESS, so there
> is no natural synchronization when irq_set_chained_handler_and_data() is
> called.
>
> If a parent interrupt fires right before the handler is cleared, the chained
> handler might be running concurrently:
>
> drivers/irqchip/irq-imx-irqsteer.c:imx_irqsteer_irq_handler() {
> ...
> 	irqmap = readl_relaxed(data->regs +
> 			       CHANSTATUS(idx, data->reg_num));
> ...
> }
>
> If imx_irqsteer_remove() proceeds to disable the hardware clock while the
> handler is still reading the CHANSTATUS MMIO registers, it could crash the
> system. Is there a way to synchronize with the executing handler before
> disabling the clock?
>
>
> [Severity: High]
> This is a pre-existing issue, but does imx_irqsteer_remove() miss PM
> runtime cleanup, leading to an unbalanced clock disable?
>
> The function unconditionally disables the clock with clk_disable_unprepare(),
> but fails to call pm_runtime_disable(). If the device is unbound via sysfs,
> the driver core calls pm_runtime_put_sync(), which executes
> imx_irqsteer_suspend() and disables the clock:
>
> drivers/irqchip/irq-imx-irqsteer.c:imx_irqsteer_suspend() {
> ...
> 	imx_irqsteer_save_regs(irqsteer_data);
> 	clk_disable_unprepare(irqsteer_data->ipg_clk);
> }
>
> Then imx_irqsteer_remove() unconditionally disables the clock again, causing
> an unbalanced WARN.
>
> Alternatively, if pm_runtime_put_sync() does not immediately suspend the
> device, imx_irqsteer_remove() disables the clock but leaves the device active
> in PM runtime. A later suspend would call imx_irqsteer_suspend(), which tries
> to access hardware registers with the clock already gated, crashing the system.
>
> Should pm_runtime_disable() be called in remove()?
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.