Re: [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure
Radu Rendec <[email protected]> Sun, 02 Aug 2026 15:19:21 -0400
| Newsgroups | org.kernel.vger.linux-mips,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 2026-07-14 at 21:24 +0800, Haofeng Li wrote: > From: Haofeng Li <[email protected]> >=20 > After mapping the register base, irq_domain_create_simple() failure > returns without unmapping it. It does, but this driver is meant to initialize once during the (early) kernel start-up and stay there for the rest of the kernel lifetime. Also, this is the Global Interrupt Controller (GIC) driver. If this fails to initialize, I very much doubt the system is usable anyway. > The CPU chained or VEIC handler is also installed before either IRQ > domain is ready. Unmapping the registers while that handler remains > published would leave a path to unmapped MMIO, ... which is probably one of the reasons why the IO range was not unmapped originally. > and a later IPI domain > failure would expose a half-initialized controller. >=20 > Unmap and clear the register base when primary domain creation fails, > and publish the CPU interrupt handler only after both domains have > been created successfully. Why? Please see my point above about the role of this driver. This driver not only has a fundamental role, but also has a different lifecycle and does not follow the cleanup paradigm of a typical driver that can be unloaded/reloaded/re-probed. >=20 > Fixes: fbea754123ae ("irqchip: mips-gic: Inline __gic_init()") >=20 > Signed-off-by: Haofeng Li <[email protected]> > --- > =C2=A0drivers/irqchip/irq-mips-gic.c | 24 +++++++++++++----------- > =C2=A01 file changed, 13 insertions(+), 11 deletions(-) >=20 > diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gi= c.c > index 19a57c5e2b2e..85fe0d8a34c5 100644 > --- a/drivers/irqchip/irq-mips-gic.c > +++ b/drivers/irqchip/irq-mips-gic.c > @@ -956,23 +956,14 @@ static int __init gic_of_init(struct device_node *n= ode, > =C2=A0 gic_shared_intrs =3D FIELD_GET(GIC_CONFIG_NUMINTERRUPTS, gicconfig= ); > =C2=A0 gic_shared_intrs =3D (gic_shared_intrs + 1) * 8; > =C2=A0 > - if (cpu_has_veic) { > - /* Always use vector 1 in EIC mode */ > - gic_cpu_pin =3D 0; > - set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, > - =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __gic_irq_dispatch); > - } else { > - gic_cpu_pin =3D cpu_vec - GIC_CPU_PIN_OFFSET; > - irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, > - gic_irq_dispatch); > - } > - > =C2=A0 gic_irq_domain =3D irq_domain_create_simple(of_fwnode_handle(node)= , > =C2=A0 =C2=A0 GIC_NUM_LOCAL_INTRS + > =C2=A0 =C2=A0 gic_shared_intrs, 0, > =C2=A0 =C2=A0 &gic_irq_domain_ops, NULL); > =C2=A0 if (!gic_irq_domain) { > =C2=A0 pr_err("Failed to add IRQ domain"); > + iounmap(mips_gic_base); > + mips_gic_base =3D NULL; > =C2=A0 return -ENXIO; > =C2=A0 } > =C2=A0 > @@ -980,6 +971,17 @@ static int __init gic_of_init(struct device_node *no= de, > =C2=A0 if (ret) > =C2=A0 return ret; > =C2=A0 > + if (cpu_has_veic) { > + /* Always use vector 1 in EIC mode */ > + gic_cpu_pin =3D 0; > + set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, > + =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __gic_irq_dispatch); > + } else { > + gic_cpu_pin =3D cpu_vec - GIC_CPU_PIN_OFFSET; > + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, > + gic_irq_dispatch); > + } > + > =C2=A0 board_bind_eic_interrupt =3D &gic_bind_eic_interrupt; > =C2=A0 > =C2=A0 /*