[PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure
Haofeng Li <[email protected]> Tue, 14 Jul 2026 21:24:43 +0800
| Newsgroups | org.kernel.vger.linux-mips,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Haofeng Li <[email protected]> After mapping the register base, irq_domain_create_simple() failure returns without unmapping it. 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, and a later IPI domain failure would expose a half-initialized controller. 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. Fixes: fbea754123ae ("irqchip: mips-gic: Inline __gic_init()") Signed-off-by: Haofeng Li <[email protected]> --- drivers/irqchip/irq-mips-gic.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.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 *node, gic_shared_intrs = FIELD_GET(GIC_CONFIG_NUMINTERRUPTS, gicconfig); gic_shared_intrs = (gic_shared_intrs + 1) * 8; - if (cpu_has_veic) { - /* Always use vector 1 in EIC mode */ - gic_cpu_pin = 0; - set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, - __gic_irq_dispatch); - } else { - gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET; - irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, - gic_irq_dispatch); - } - gic_irq_domain = irq_domain_create_simple(of_fwnode_handle(node), GIC_NUM_LOCAL_INTRS + gic_shared_intrs, 0, &gic_irq_domain_ops, NULL); if (!gic_irq_domain) { pr_err("Failed to add IRQ domain"); + iounmap(mips_gic_base); + mips_gic_base = NULL; return -ENXIO; } @@ -980,6 +971,17 @@ static int __init gic_of_init(struct device_node *node, if (ret) return ret; + if (cpu_has_veic) { + /* Always use vector 1 in EIC mode */ + gic_cpu_pin = 0; + set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, + __gic_irq_dispatch); + } else { + gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET; + irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, + gic_irq_dispatch); + } + board_bind_eic_interrupt = &gic_bind_eic_interrupt; /* -- 2.25.1