* [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
@ 2026-07-14 13:24 ` Haofeng Li
2026-07-28 17:36 ` Florian Fainelli
2026-07-14 13:24 ` [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error Haofeng Li
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Florian Fainelli,
Broadcom internal kernel review list, Kevin Cernekee, linux-mips,
linux-arm-kernel
From: Haofeng Li <lihaofeng@kylinos.cn>
bcm7038_l1_init_one() stores the allocated CPU object in
intc->cpus[idx] before mapping its registers and parent interrupt.
Failures after that allocation leak the CPU object and possibly its
MMIO mapping.
A later IRQ domain allocation failure also frees intc while leaving
parent mappings and chained handlers installed for CPUs initialized
successfully. Those handlers retain intc as their data and can access
freed memory.
Free the current CPU object on local failures. Remember every parent
IRQ so the common error path can disable wake when it was enabled,
remove the chained handler, dispose the mapping, unmap the registers,
and free the CPU object before freeing intc.
Fixes: 5f7f0317ed28 ("IRQCHIP: Add new driver for BCM7038-style level 1 interrupt controllers")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-bcm7038-l1.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index 54a8557ef557..b42c4f4df6bf 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -49,6 +49,8 @@ struct bcm7038_l1_chip {
struct bcm7038_l1_cpu {
void __iomem *map_base;
+ unsigned int parent_irq;
+ bool wake_enabled;
u32 mask_cache[];
};
@@ -247,8 +249,11 @@ static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
return -ENOMEM;
cpu->map_base = ioremap(res.start, sz);
- if (!cpu->map_base)
+ if (!cpu->map_base) {
+ kfree(cpu);
+ intc->cpus[idx] = NULL;
return -ENOMEM;
+ }
for (i = 0; i < n_words; i++) {
l1_writel(~intc->irq_fwd_mask[i],
@@ -261,12 +266,17 @@ static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
parent_irq = irq_of_parse_and_map(dn, idx);
if (!parent_irq) {
pr_err("failed to map parent interrupt %d\n", parent_irq);
+ iounmap(cpu->map_base);
+ kfree(cpu);
+ intc->cpus[idx] = NULL;
return -EINVAL;
}
- if (of_property_read_bool(dn, "brcm,irq-can-wake"))
- enable_irq_wake(parent_irq);
+ if (of_property_read_bool(dn, "brcm,irq-can-wake") &&
+ !enable_irq_wake(parent_irq))
+ cpu->wake_enabled = true;
+ cpu->parent_irq = parent_irq;
irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle,
intc);
@@ -408,7 +418,7 @@ static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *pa
if (idx)
break;
pr_err("failed to remap intc L1 registers\n");
- goto out_free;
+ goto out_unmap;
}
}
@@ -440,6 +450,12 @@ static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *pa
struct bcm7038_l1_cpu *cpu = intc->cpus[idx];
if (cpu) {
+ if (cpu->parent_irq) {
+ if (cpu->wake_enabled)
+ disable_irq_wake(cpu->parent_irq);
+ irq_set_chained_handler_and_data(cpu->parent_irq, NULL, NULL);
+ irq_dispose_mapping(cpu->parent_irq);
+ }
if (cpu->map_base)
iounmap(cpu->map_base);
kfree(cpu);
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths
2026-07-14 13:24 ` [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths Haofeng Li
@ 2026-07-28 17:36 ` Florian Fainelli
0 siblings, 0 replies; 13+ messages in thread
From: Florian Fainelli @ 2026-07-28 17:36 UTC (permalink / raw)
To: Haofeng Li, tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Florian Fainelli,
Broadcom internal kernel review list, Kevin Cernekee, linux-mips,
linux-arm-kernel
On 7/14/26 06:24, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> bcm7038_l1_init_one() stores the allocated CPU object in
> intc->cpus[idx] before mapping its registers and parent interrupt.
> Failures after that allocation leak the CPU object and possibly its
> MMIO mapping.
>
> A later IRQ domain allocation failure also frees intc while leaving
> parent mappings and chained handlers installed for CPUs initialized
> successfully. Those handlers retain intc as their data and can access
> freed memory.
>
> Free the current CPU object on local failures. Remember every parent
> IRQ so the common error path can disable wake when it was enabled,
> remove the chained handler, dispose the mapping, unmap the registers,
> and free the CPU object before freeing intc.
>
> Fixes: 5f7f0317ed28 ("IRQCHIP: Add new driver for BCM7038-style level 1 interrupt controllers")
>
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
> ---
> drivers/irqchip/irq-bcm7038-l1.c | 24 ++++++++++++++++++++----
> 1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
> index 54a8557ef557..b42c4f4df6bf 100644
> --- a/drivers/irqchip/irq-bcm7038-l1.c
> +++ b/drivers/irqchip/irq-bcm7038-l1.c
> @@ -49,6 +49,8 @@ struct bcm7038_l1_chip {
>
> struct bcm7038_l1_cpu {
> void __iomem *map_base;
> + unsigned int parent_irq;
> + bool wake_enabled;
> u32 mask_cache[];
> };
>
> @@ -247,8 +249,11 @@ static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
> return -ENOMEM;
>
> cpu->map_base = ioremap(res.start, sz);
> - if (!cpu->map_base)
> + if (!cpu->map_base) {
> + kfree(cpu);
> + intc->cpus[idx] = NULL;
This pattern repeats below, consider creating a new label, that would do
the 'cpu' variable freeing and assigng intc->cpus[idx] to NULL?
> return -ENOMEM;
> + }
>
> for (i = 0; i < n_words; i++) {
> l1_writel(~intc->irq_fwd_mask[i],
> @@ -261,12 +266,17 @@ static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
> parent_irq = irq_of_parse_and_map(dn, idx);
> if (!parent_irq) {
> pr_err("failed to map parent interrupt %d\n", parent_irq);
> + iounmap(cpu->map_base);
And this would belong to a new label as well
> + kfree(cpu);
> + intc->cpus[idx] = NULL;
That new label would be used here.
> return -EINVAL;
> }
>
> - if (of_property_read_bool(dn, "brcm,irq-can-wake"))
> - enable_irq_wake(parent_irq);
> + if (of_property_read_bool(dn, "brcm,irq-can-wake") &&
> + !enable_irq_wake(parent_irq))
> + cpu->wake_enabled = true;
>
> + cpu->parent_irq = parent_irq;
> irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle,
> intc);
>
> @@ -408,7 +418,7 @@ static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *pa
> if (idx)
> break;
> pr_err("failed to remap intc L1 registers\n");
> - goto out_free;
> + goto out_unmap;
> }
> }
>
> @@ -440,6 +450,12 @@ static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *pa
> struct bcm7038_l1_cpu *cpu = intc->cpus[idx];
>
> if (cpu) {
> + if (cpu->parent_irq) {
> + if (cpu->wake_enabled)
> + disable_irq_wake(cpu->parent_irq);
> + irq_set_chained_handler_and_data(cpu->parent_irq, NULL, NULL);
> + irq_dispose_mapping(cpu->parent_irq);
> + }
> if (cpu->map_base)
> iounmap(cpu->map_base);
> kfree(cpu);
--
Florian
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
2026-07-14 13:24 ` [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-08-02 16:31 ` Radu Rendec
2026-07-14 13:24 ` [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure Haofeng Li
` (4 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Huacai Chen, Jiaxun Yang,
Jianmin Lv, Marc Zyngier, linux-mips
From: Haofeng Li <lihaofeng@kylinos.cn>
For revision > 1, liointc_init() maps per-core ISR regions with
of_iomap(). out_iounmap only unmapped the main base, leaking successful
per-core mappings on later failures.
On the error path, iounmap any core_isr entry that is not an offset into
the main base mapping.
Fixes: 0858ed035a85 ("irqchip/loongson-liointc: Add ACPI init support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-loongson-liointc.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index cf44a333b9c8..6451d8b466ce 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -312,6 +312,14 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
out_free_domain:
irq_domain_remove(domain);
out_iounmap:
+ if (revision > 1) {
+ for (i = 0; i < LIOINTC_NUM_CORES; i++) {
+ void __iomem *core_base = base + LIOINTC_REG_INTC_STATUS(i);
+
+ if (priv->core_isr[i] && priv->core_isr[i] != core_base)
+ iounmap(priv->core_isr[i]);
+ }
+ }
iounmap(base);
out_free_priv:
kfree(priv);
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error
2026-07-14 13:24 ` [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error Haofeng Li
@ 2026-08-02 16:31 ` Radu Rendec
0 siblings, 0 replies; 13+ messages in thread
From: Radu Rendec @ 2026-08-02 16:31 UTC (permalink / raw)
To: Haofeng Li, tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Huacai Chen, Jiaxun Yang,
Jianmin Lv, Marc Zyngier, linux-mips
On Tue, 2026-07-14 at 21:24 +0800, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> For revision > 1, liointc_init() maps per-core ISR regions with
> of_iomap(). out_iounmap only unmapped the main base, leaking successful
> per-core mappings on later failures.
>
> On the error path, iounmap any core_isr entry that is not an offset into
> the main base mapping.
>
> Fixes: 0858ed035a85 ("irqchip/loongson-liointc: Add ACPI init support")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
> ---
> drivers/irqchip/irq-loongson-liointc.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
> index cf44a333b9c8..6451d8b466ce 100644
> --- a/drivers/irqchip/irq-loongson-liointc.c
> +++ b/drivers/irqchip/irq-loongson-liointc.c
> @@ -312,6 +312,14 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
> out_free_domain:
> irq_domain_remove(domain);
> out_iounmap:
> + if (revision > 1) {
> + for (i = 0; i < LIOINTC_NUM_CORES; i++) {
> + void __iomem *core_base = base + LIOINTC_REG_INTC_STATUS(i);
> +
> + if (priv->core_isr[i] && priv->core_isr[i] != core_base)
The first condition here is unnecessary. It's safe to call iounmap()
with a NULL pointer (like most deallocation functions in Linux).
Can you please explain why the second condition is needed? Even if the
physical ranges happen to overlap, they are mapped independently via
the of_iomap() call earlier in the function. That allocates a separate
vm area (and a PTE) that still needs to be freed.
FWIW, in the two relevant device trees I could find, the physical
ranges do *not* overlap:
arch/loongarch/boot/dts/loongson-2k0500.dtsi
arch/loongarch/boot/dts/loongson-2k1000.dtsi
> + iounmap(priv->core_isr[i]);
> + }
> + }
> iounmap(base);
> out_free_priv:
> kfree(priv);
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
2026-07-14 13:24 ` [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths Haofeng Li
2026-07-14 13:24 ` [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-08-02 19:19 ` Radu Rendec
2026-07-14 13:24 ` [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails Haofeng Li
` (3 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Thomas Bogendoerfer,
Marc Zyngier, Paul Burton, linux-mips
From: Haofeng Li <lihaofeng@kylinos.cn>
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 <lihaofeng@kylinos.cn>
---
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
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure
2026-07-14 13:24 ` [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure Haofeng Li
@ 2026-08-02 19:19 ` Radu Rendec
0 siblings, 0 replies; 13+ messages in thread
From: Radu Rendec @ 2026-08-02 19:19 UTC (permalink / raw)
To: Haofeng Li, tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Thomas Bogendoerfer,
Marc Zyngier, Paul Burton, linux-mips
On Tue, 2026-07-14 at 21:24 +0800, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> 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.
>
> 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.
>
> Fixes: fbea754123ae ("irqchip: mips-gic: Inline __gic_init()")
>
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
> ---
> 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;
>
> /*
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
` (2 preceding siblings ...)
2026-07-14 13:24 ` [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-08-02 19:26 ` Radu Rendec
2026-07-14 13:24 ` [PATCH 09/16] irqchip/econet: clean up VEIC initialization Haofeng Li
` (2 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Thomas Bogendoerfer,
Samuel Holland, Marc Zyngier, linux-mips
From: Haofeng Li <lihaofeng@kylinos.cn>
If gic_register_ipi_domain() fails, the primary IRQ domain and the
mapped register base are left allocated.
At this point the CPU interrupt handler has not yet been published.
Remove the primary domain, unmap the register base, and clear both
global pointers before returning the error.
Fixes: 8190cc572981 ("irqchip/mips-gic: Only register IPI domain when SMP is enabled")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-mips-gic.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 85fe0d8a34c5..2f2ba54f227f 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -968,8 +968,13 @@ static int __init gic_of_init(struct device_node *node,
}
ret = gic_register_ipi_domain(node);
- if (ret)
+ if (ret) {
+ irq_domain_remove(gic_irq_domain);
+ gic_irq_domain = NULL;
+ iounmap(mips_gic_base);
+ mips_gic_base = NULL;
return ret;
+ }
if (cpu_has_veic) {
/* Always use vector 1 in EIC mode */
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails
2026-07-14 13:24 ` [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails Haofeng Li
@ 2026-08-02 19:26 ` Radu Rendec
0 siblings, 0 replies; 13+ messages in thread
From: Radu Rendec @ 2026-08-02 19:26 UTC (permalink / raw)
To: Haofeng Li, tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Thomas Bogendoerfer,
Samuel Holland, Marc Zyngier, linux-mips
On Tue, 2026-07-14 at 21:24 +0800, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> If gic_register_ipi_domain() fails, the primary IRQ domain and the
> mapped register base are left allocated.
>
> At this point the CPU interrupt handler has not yet been published.
> Remove the primary domain, unmap the register base, and clear both
> global pointers before returning the error.
IMO this patch should be squashed into the previous one in the series
because it fixes a similar problem in the same function of the same
driver, and the change is very much related.
But please see my comments to the previous patch. I think you are
trying to fix a problem that does not exist.
> Fixes: 8190cc572981 ("irqchip/mips-gic: Only register IPI domain when SMP is enabled")
>
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
> ---
> drivers/irqchip/irq-mips-gic.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
> index 85fe0d8a34c5..2f2ba54f227f 100644
> --- a/drivers/irqchip/irq-mips-gic.c
> +++ b/drivers/irqchip/irq-mips-gic.c
> @@ -968,8 +968,13 @@ static int __init gic_of_init(struct device_node *node,
> }
>
> ret = gic_register_ipi_domain(node);
> - if (ret)
> + if (ret) {
> + irq_domain_remove(gic_irq_domain);
> + gic_irq_domain = NULL;
> + iounmap(mips_gic_base);
> + mips_gic_base = NULL;
> return ret;
> + }
>
> if (cpu_has_veic) {
> /* Always use vector 1 in EIC mode */
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 09/16] irqchip/econet: clean up VEIC initialization
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
` (3 preceding siblings ...)
2026-07-14 13:24 ` [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-07-23 1:09 ` Caleb James DeLisle
2026-07-14 13:24 ` [PATCH 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure Haofeng Li
2026-07-14 13:24 ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx; +Cc: linux-kernel, Haofeng Li, Haofeng Li, Caleb James DeLisle,
linux-mips
From: Haofeng Li <lihaofeng@kylinos.cn>
When cpu_has_veic is set, econet_cpu_init() failure returns without
tearing down the already created IRQ domain, ioremap, memory region,
or parent IRQ mapping. The parent interrupt-controller node obtained
while finding the IPI domain also retains an OF node reference on both
success and failure.
Drop the parent node reference after the domain lookup and route VEIC
initialization failures through the existing resource cleanup labels
after removing the IRQ domain.
Fixes: 2ee2a685ee83 ("irqchip/econet-en751221: Support MIPS 34Kc VEIC mode")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-econet-en751221.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-econet-en751221.c b/drivers/irqchip/irq-econet-en751221.c
index 2ca5d901866f..f6f890b3f881 100644
--- a/drivers/irqchip/irq-econet-en751221.c
+++ b/drivers/irqchip/irq-econet-en751221.c
@@ -378,6 +378,7 @@ static int __init econet_cpu_init(struct device_node *node)
}
econet_intc.ipi_domain = irq_find_matching_host(parent_intc, DOMAIN_BUS_IPI);
+ of_node_put(parent_intc);
if (!econet_intc.ipi_domain) {
pr_err("%pOF: Failed to find parent %s\n", node, "IPI domain");
return -ENODEV;
@@ -459,7 +460,7 @@ static int __init econet_intc_of_init(struct device_node *node, struct device_no
ret = econet_cpu_init(node);
if (ret)
- return ret;
+ goto err_remove_domain;
} else {
irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain);
}
@@ -468,6 +469,8 @@ static int __init econet_intc_of_init(struct device_node *node, struct device_no
return 0;
+err_remove_domain:
+ irq_domain_remove(domain);
err_unmap:
iounmap(econet_intc.membase);
err_release:
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 09/16] irqchip/econet: clean up VEIC initialization
2026-07-14 13:24 ` [PATCH 09/16] irqchip/econet: clean up VEIC initialization Haofeng Li
@ 2026-07-23 1:09 ` Caleb James DeLisle
0 siblings, 0 replies; 13+ messages in thread
From: Caleb James DeLisle @ 2026-07-23 1:09 UTC (permalink / raw)
To: Haofeng Li, tglx; +Cc: linux-kernel, Haofeng Li, Haofeng Li, linux-mips
On 14/07/2026 15:24, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> When cpu_has_veic is set, econet_cpu_init() failure returns without
> tearing down the already created IRQ domain, ioremap, memory region,
> or parent IRQ mapping. The parent interrupt-controller node obtained
> while finding the IPI domain also retains an OF node reference on both
> success and failure.
>
> Drop the parent node reference after the domain lookup and route VEIC
> initialization failures through the existing resource cleanup labels
> after removing the IRQ domain.
>
> Fixes: 2ee2a685ee83 ("irqchip/econet-en751221: Support MIPS 34Kc VEIC mode")
>
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
Tested-by: Caleb James DeLisle <cjd@cjdns.fr>
> ---
> drivers/irqchip/irq-econet-en751221.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-econet-en751221.c b/drivers/irqchip/irq-econet-en751221.c
> index 2ca5d901866f..f6f890b3f881 100644
> --- a/drivers/irqchip/irq-econet-en751221.c
> +++ b/drivers/irqchip/irq-econet-en751221.c
> @@ -378,6 +378,7 @@ static int __init econet_cpu_init(struct device_node *node)
> }
>
> econet_intc.ipi_domain = irq_find_matching_host(parent_intc, DOMAIN_BUS_IPI);
> + of_node_put(parent_intc);
> if (!econet_intc.ipi_domain) {
> pr_err("%pOF: Failed to find parent %s\n", node, "IPI domain");
> return -ENODEV;
> @@ -459,7 +460,7 @@ static int __init econet_intc_of_init(struct device_node *node, struct device_no
> ret = econet_cpu_init(node);
>
> if (ret)
> - return ret;
> + goto err_remove_domain;
> } else {
> irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain);
> }
> @@ -468,6 +469,8 @@ static int __init econet_intc_of_init(struct device_node *node, struct device_no
>
> return 0;
>
> +err_remove_domain:
> + irq_domain_remove(domain);
> err_unmap:
> iounmap(econet_intc.membase);
> err_release:
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
` (4 preceding siblings ...)
2026-07-14 13:24 ` [PATCH 09/16] irqchip/econet: clean up VEIC initialization Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-07-14 13:24 ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li
6 siblings, 0 replies; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Huacai Chen, Jiaxun Yang,
Marc Zyngier, Binbin Zhou, linux-mips
From: Haofeng Li <lihaofeng@kylinos.cn>
eiointc_init() publishes priv through the IRQ domain, chained
handlers, eiointc_priv[], syscore operations, and CPU hotplug state.
If subsequent cascade initialization fails, jumping to
out_free_handle frees priv and its fwnode while all of those users
remain live.
Cascade initialization may also have created PCH PIC, MSI, or LPC
child domains before reporting an error, so removing the EIOINTC
parent at that point is not a safe rollback.
After eiointc_init() succeeds, keep the published controller alive and
propagate the cascade error without freeing it. Before ownership is
transferred, validate the parent mapping and dispose it if
eiointc_init() fails. Preserve the actual error code on all cleanup
paths.
Fixes: a3f1132c4c6b ("irqchip/loongson-eiointc: Add DT init support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-loongson-eiointc.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
index a9e8b481d31d..d2310a1ebbd6 100644
--- a/drivers/irqchip/irq-loongson-eiointc.c
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -580,7 +580,7 @@ static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq,
int __init eiointc_acpi_init(struct irq_domain *parent,
struct acpi_madt_eio_pic *acpi_eiointc)
{
- int parent_irq, ret;
+ int parent_irq, ret = -ENOMEM;
struct eiointc_priv *priv;
int node;
@@ -599,10 +599,12 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
priv->node = acpi_eiointc->node;
priv->parent_hwirq = acpi_eiointc->cascade;
parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
+ if (!parent_irq)
+ goto out_free_handle;
ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map);
if (ret < 0)
- goto out_free_handle;
+ goto out_dispose_mapping;
if (cpu_has_flatmode)
node = early_cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
@@ -612,18 +614,17 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
acpi_set_vec_parent(node, priv->eiointc_domain, msi_group);
ret = acpi_cascade_irqdomain_init();
- if (ret < 0)
- goto out_free_handle;
-
return ret;
+out_dispose_mapping:
+ irq_dispose_mapping(parent_irq);
out_free_handle:
irq_domain_free_fwnode(priv->domain_handle);
priv->domain_handle = NULL;
out_free_priv:
kfree(priv);
- return -ENOMEM;
+ return ret;
}
static int __init eiointc_of_init(struct device_node *of_node,
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling
[not found] ` <20260714132453.3302672-1-920484857@qq.com>
` (5 preceding siblings ...)
2026-07-14 13:24 ` [PATCH 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure Haofeng Li
@ 2026-07-14 13:24 ` Haofeng Li
2026-07-28 15:57 ` Florian Fainelli
6 siblings, 1 reply; 13+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Florian Fainelli,
Broadcom internal kernel review list, Marc Zyngier, linux-mips,
linux-arm-kernel
From: Haofeng Li <lihaofeng@kylinos.cn>
When platform_irq_count() fails or returns zero, probe reported -ENOMEM
even though no memory allocation failed. Negative values such as
-EPROBE_DEFER were also discarded, which breaks deferred probe.
Propagate negative errno from platform_irq_count(), and return -EINVAL
only for a zero parent interrupt count.
Fixes: 3ac268d5ed22 ("irqchip/irq-bcm7120-l2: Switch to IRQCHIP_PLATFORM_DRIVER")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
drivers/irqchip/irq-bcm7120-l2.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c
index a98f0ee46b6c..9f412c0be6d7 100644
--- a/drivers/irqchip/irq-bcm7120-l2.c
+++ b/drivers/irqchip/irq-bcm7120-l2.c
@@ -225,9 +225,13 @@ static int bcm7120_l2_intc_probe(struct platform_device *pdev, struct device_nod
return -ENOMEM;
data->num_parent_irqs = platform_irq_count(pdev);
- if (data->num_parent_irqs <= 0) {
+ if (data->num_parent_irqs < 0) {
+ ret = data->num_parent_irqs;
+ goto out_unmap;
+ }
+ if (!data->num_parent_irqs) {
pr_err("invalid number of parent interrupts\n");
- ret = -ENOMEM;
+ ret = -EINVAL;
goto out_unmap;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling
2026-07-14 13:24 ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li
@ 2026-07-28 15:57 ` Florian Fainelli
0 siblings, 0 replies; 13+ messages in thread
From: Florian Fainelli @ 2026-07-28 15:57 UTC (permalink / raw)
To: Haofeng Li, tglx
Cc: linux-kernel, Haofeng Li, Haofeng Li, Florian Fainelli,
Broadcom internal kernel review list, Marc Zyngier, linux-mips,
linux-arm-kernel
On 7/14/26 06:24, Haofeng Li wrote:
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> When platform_irq_count() fails or returns zero, probe reported -ENOMEM
> even though no memory allocation failed. Negative values such as
> -EPROBE_DEFER were also discarded, which breaks deferred probe.
>
> Propagate negative errno from platform_irq_count(), and return -EINVAL
> only for a zero parent interrupt count.
>
> Fixes: 3ac268d5ed22 ("irqchip/irq-bcm7120-l2: Switch to IRQCHIP_PLATFORM_DRIVER")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply [flat|nested] 13+ messages in thread