Re: [PATCH v5 5/9] irqchip/imx-irqsteer: Mask all interrupts in probe()
From: Radu Rendec
Date: Sun Aug 30 2026 - 14:51:34 EST
On Fri, 2026-08-21 at 19:10 +0900, Zhipeng.wang_1@xxxxxxxxxxx wrote:
> From: Zhipeng Wang <zhipeng.wang_1@xxxxxxx>
>
> probe() sets up the chained handlers without first masking the input
> interrupts. For a built-in driver this happened to be harmless because
> CHANMASK resets to all-masked, but once the driver can be unloaded and
> reloaded a child interrupt left unmasked at unload time survives in
> hardware. On the next probe() the parent interrupts are re-mapped and
> unmasked before the new domain is ready, so a still-asserted line
> immediately storms the parent with no handler to service it.
>
> Mask all interrupts in probe() before wiring up the chained handlers.
> CHANMASK uses inverted polarity (a set bit enables the interrupt), so
> masking means writing zero. This mirrors the sibling NXP chained mux
> irq-imx-intmux.c, which masks all sources at probe() time.
>
> Masking is only done in probe(), not in remove(): the next probe()
> quiesces the hardware before it re-maps and unmasks the parent
> interrupts, which is the only window in which a stale line could storm.
> Masking in remove() would also mean touching CHANMASK while the device
> may already be runtime-suspended with the clock gated.
>
> Signed-off-by: Zhipeng Wang <zhipeng.wang_1@xxxxxxx>
> ---
> drivers/irqchip/irq-imx-irqsteer.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
> index 071ab1ac1fe9..b63bf957ab88 100644
> --- a/drivers/irqchip/irq-imx-irqsteer.c
> +++ b/drivers/irqchip/irq-imx-irqsteer.c
> @@ -239,6 +239,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));
> +
> struct irq_domain_info info = {
> .fwnode = dev_fwnode(&pdev->dev),
> .size = data->reg_num * 32,
Reviewed-by: Radu Rendec <radu@xxxxxxxxxx>