All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] irqchip: harden initialization error paths
@ 2026-07-14 12:23 ` Haofeng Li
  0 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 12:23 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Samuel Holland,
	linux-riscv

An audit of irqchip initialization and allocation error paths found a
collection of resource leaks and lifetime issues across several drivers.

The most serious cases leave interrupt handlers or other globally visible
state pointing at memory that is subsequently freed or unmapped.  Other
cases leak IRQ domains, parent mappings, MMIO mappings, allocation bitmap
regions, or allocated objects when initialization fails part-way through.
The series also fixes an unbounded IMSIC MMIO lookup, a possible NULL MMIO
access in the NVIDIA T241 workaround, and two cases where useful error
information is lost or reported incorrectly.

The changes are confined to failure handling; successful initialization
paths are left unchanged.  The MIPS GIC fixes in patches 7 and 8 build on
each other, as do the Realtek RTL fixes in patches 12 and 13.  The remaining
patches are independent.

The issues addressed are:

  - bound MMIO lookup and make allocation cleanup NULL-safe;
  - roll back partially allocated IRQs, domains and bitmap regions;
  - do not free or unmap state after it has been published to live users;
  - distinguish managed from unmanaged MMIO mappings during cleanup;
  - release parent IRQ mappings, per-CPU mappings and OF node references;
  - preserve deferred-probe errors and report the correct reset error.

Haofeng Li (16):
  irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
  irqchip/loongarch-ir: fix redirect free and alloc leaks
  irqchip/sifive-plic: do not iounmap devm mappings
  irqchip/crossbar: fix allocation and init cleanup
  irqchip/bcm7038-l1: clean up init failure paths
  irqchip/loongson-liointc: unmap per-core iomaps on error
  irqchip/mips-gic: clean up IRQ domain creation failure
  irqchip/mips-gic: clean up if IPI domain registration fails
  irqchip/econet: clean up VEIC initialization
  irqchip/aspeed-vic: publish handler only after domain creation
  irqchip/loongson-eiointc: preserve live state on cascade failure
  irqchip/realtek-rtl: unmap per-CPU bases on init failure
  irqchip/realtek-rtl: dispose parent mapping on domain failure
  irqchip/renesas-rzg2l: fix wrong errno in reset error log
  irqchip/gic-v3: fail T241 quirk if alias ioremap fails
  irqchip/bcm7120-l2: fix parent IRQ count error handling

 drivers/irqchip/irq-aspeed-vic.c        | 23 ++++++++++++++----
 drivers/irqchip/irq-bcm7038-l1.c        | 24 +++++++++++++++----
 drivers/irqchip/irq-bcm7120-l2.c        |  8 +++++--
 drivers/irqchip/irq-crossbar.c          | 23 ++++++++++++++++--
 drivers/irqchip/irq-econet-en751221.c   |  5 +++-
 drivers/irqchip/irq-gic-v3.c            | 11 ++++++++-
 drivers/irqchip/irq-loongarch-ir.c      | 21 +++++++++++++++--
 drivers/irqchip/irq-loongson-eiointc.c  | 13 ++++++-----
 drivers/irqchip/irq-loongson-liointc.c  |  8 +++++++
 drivers/irqchip/irq-mips-gic.c          | 31 +++++++++++++++----------
 drivers/irqchip/irq-realtek-rtl.c       | 28 ++++++++++++++++++----
 drivers/irqchip/irq-renesas-rzg2l.c     |  2 +-
 drivers/irqchip/irq-riscv-imsic-state.c | 12 ++++++----
 drivers/irqchip/irq-sifive-plic.c       |  4 +++-
 14 files changed, 168 insertions(+), 45 deletions(-)


base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
-- 
2.25.1

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 00/16] irqchip: harden initialization error paths
@ 2026-07-14 12:23 ` Haofeng Li
  0 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 12:23 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Samuel Holland,
	linux-riscv

An audit of irqchip initialization and allocation error paths found a
collection of resource leaks and lifetime issues across several drivers.

The most serious cases leave interrupt handlers or other globally visible
state pointing at memory that is subsequently freed or unmapped.  Other
cases leak IRQ domains, parent mappings, MMIO mappings, allocation bitmap
regions, or allocated objects when initialization fails part-way through.
The series also fixes an unbounded IMSIC MMIO lookup, a possible NULL MMIO
access in the NVIDIA T241 workaround, and two cases where useful error
information is lost or reported incorrectly.

The changes are confined to failure handling; successful initialization
paths are left unchanged.  The MIPS GIC fixes in patches 7 and 8 build on
each other, as do the Realtek RTL fixes in patches 12 and 13.  The remaining
patches are independent.

The issues addressed are:

  - bound MMIO lookup and make allocation cleanup NULL-safe;
  - roll back partially allocated IRQs, domains and bitmap regions;
  - do not free or unmap state after it has been published to live users;
  - distinguish managed from unmanaged MMIO mappings during cleanup;
  - release parent IRQ mappings, per-CPU mappings and OF node references;
  - preserve deferred-probe errors and report the correct reset error.

Haofeng Li (16):
  irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
  irqchip/loongarch-ir: fix redirect free and alloc leaks
  irqchip/sifive-plic: do not iounmap devm mappings
  irqchip/crossbar: fix allocation and init cleanup
  irqchip/bcm7038-l1: clean up init failure paths
  irqchip/loongson-liointc: unmap per-core iomaps on error
  irqchip/mips-gic: clean up IRQ domain creation failure
  irqchip/mips-gic: clean up if IPI domain registration fails
  irqchip/econet: clean up VEIC initialization
  irqchip/aspeed-vic: publish handler only after domain creation
  irqchip/loongson-eiointc: preserve live state on cascade failure
  irqchip/realtek-rtl: unmap per-CPU bases on init failure
  irqchip/realtek-rtl: dispose parent mapping on domain failure
  irqchip/renesas-rzg2l: fix wrong errno in reset error log
  irqchip/gic-v3: fail T241 quirk if alias ioremap fails
  irqchip/bcm7120-l2: fix parent IRQ count error handling

 drivers/irqchip/irq-aspeed-vic.c        | 23 ++++++++++++++----
 drivers/irqchip/irq-bcm7038-l1.c        | 24 +++++++++++++++----
 drivers/irqchip/irq-bcm7120-l2.c        |  8 +++++--
 drivers/irqchip/irq-crossbar.c          | 23 ++++++++++++++++--
 drivers/irqchip/irq-econet-en751221.c   |  5 +++-
 drivers/irqchip/irq-gic-v3.c            | 11 ++++++++-
 drivers/irqchip/irq-loongarch-ir.c      | 21 +++++++++++++++--
 drivers/irqchip/irq-loongson-eiointc.c  | 13 ++++++-----
 drivers/irqchip/irq-loongson-liointc.c  |  8 +++++++
 drivers/irqchip/irq-mips-gic.c          | 31 +++++++++++++++----------
 drivers/irqchip/irq-realtek-rtl.c       | 28 ++++++++++++++++++----
 drivers/irqchip/irq-renesas-rzg2l.c     |  2 +-
 drivers/irqchip/irq-riscv-imsic-state.c | 12 ++++++----
 drivers/irqchip/irq-sifive-plic.c       |  4 +++-
 14 files changed, 168 insertions(+), 45 deletions(-)


base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
-- 
2.25.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 01/16] irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
  2026-07-14 12:23 ` Haofeng Li
@ 2026-07-14 12:23   ` Haofeng Li
  -1 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 12:23 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Anup Patel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
	linux-riscv

The MSI page lookup loop uses:

	for (j = 0; nr_mmios; j++)

When nr_mmios is non-zero the condition is always true, so j is never
bounded. If reloff does not fall in any MMIO region the loop indexes
past mmios[] and may hang or fault.

Also, mmios_va starts as NULL. If its allocation fails, the out_iounmap
path indexes mmios_va[i] and NULL-dereferences.

Bound the loop with j < nr_mmios, and guard the iounmap/kfree cleanup
with if (mmios_va).

Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-riscv-imsic-state.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b8d1bbbf42f7..19f74cf79988 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -896,7 +896,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
 		index = nr_mmios;
 		reloff = i * BIT(global->guest_index_bits) *
 			 IMSIC_MMIO_PAGE_SZ;
-		for (j = 0; nr_mmios; j++) {
+		for (j = 0; j < nr_mmios; j++) {
 			if (reloff < resource_size(&mmios[j])) {
 				index = j;
 				break;
@@ -953,11 +953,13 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
 out_local_cleanup:
 	imsic_local_cleanup();
 out_iounmap:
-	for (i = 0; i < nr_mmios; i++) {
-		if (mmios_va[i])
-			iounmap(mmios_va[i]);
+	if (mmios_va) {
+		for (i = 0; i < nr_mmios; i++) {
+			if (mmios_va[i])
+				iounmap(mmios_va[i]);
+		}
+		kfree(mmios_va);
 	}
-	kfree(mmios_va);
 	kfree(mmios);
 out_free_local:
 	free_percpu(imsic->global.local);
-- 
2.25.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 01/16] irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
@ 2026-07-14 12:23   ` Haofeng Li
  0 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 12:23 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Anup Patel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
	linux-riscv

The MSI page lookup loop uses:

	for (j = 0; nr_mmios; j++)

When nr_mmios is non-zero the condition is always true, so j is never
bounded. If reloff does not fall in any MMIO region the loop indexes
past mmios[] and may hang or fault.

Also, mmios_va starts as NULL. If its allocation fails, the out_iounmap
path indexes mmios_va[i] and NULL-dereferences.

Bound the loop with j < nr_mmios, and guard the iounmap/kfree cleanup
with if (mmios_va).

Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-riscv-imsic-state.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b8d1bbbf42f7..19f74cf79988 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -896,7 +896,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
 		index = nr_mmios;
 		reloff = i * BIT(global->guest_index_bits) *
 			 IMSIC_MMIO_PAGE_SZ;
-		for (j = 0; nr_mmios; j++) {
+		for (j = 0; j < nr_mmios; j++) {
 			if (reloff < resource_size(&mmios[j])) {
 				index = j;
 				break;
@@ -953,11 +953,13 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
 out_local_cleanup:
 	imsic_local_cleanup();
 out_iounmap:
-	for (i = 0; i < nr_mmios; i++) {
-		if (mmios_va[i])
-			iounmap(mmios_va[i]);
+	if (mmios_va) {
+		for (i = 0; i < nr_mmios; i++) {
+			if (mmios_va[i])
+				iounmap(mmios_va[i]);
+		}
+		kfree(mmios_va);
 	}
-	kfree(mmios_va);
 	kfree(mmios);
 out_free_local:
 	free_percpu(imsic->global.local);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 02/16] irqchip/loongarch-ir: fix redirect free and alloc leaks
  2026-07-14 12:23 ` Haofeng Li
  (?)
  (?)
@ 2026-07-14 12:23 ` Haofeng Li
  -1 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 12:23 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Huacai Chen, WANG Xuerui,
	Tianyang Zhang, Liupu Wang, loongarch

redirect_irde_free() ignores its irde argument and always frees
redirect_descs (node 0). Multi-node teardown therefore leaks non-zero
nodes.

On the alloc path, a failed redirect_table_alloc() after
irq_domain_alloc_irqs_parent() returns without freeing parent IRQs.
A mid-loop gpid allocation failure also leaks the current item (chip_data
is not set yet) and never releases the bitmap region obtained from
bitmap_find_free_region().

Free &irde->ird_table and &irde->inv_queue, free parent IRQs on table
alloc failure, kfree(item) on gpid failure, and release the full bitmap
region on the error path.

Fixes: 71619266e0a2 ("irqchip/loongarch-ir: Add IR (interrupt redirection) irqchip support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-loongarch-ir.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-loongarch-ir.c b/drivers/irqchip/irq-loongarch-ir.c
index 21c649a89a70..695dfef6570a 100644
--- a/drivers/irqchip/irq-loongarch-ir.c
+++ b/drivers/irqchip/irq-loongarch-ir.c
@@ -219,6 +219,20 @@ static int redirect_table_alloc(int node, u32 nr_irqs)
 	return index;
 }
 
+static void redirect_table_free_region(int node, int index, u32 nr_irqs)
+{
+	struct redirect_table *ird_table = &redirect_descs[node].ird_table;
+	int order = 0;
+
+	if (nr_irqs > 1) {
+		nr_irqs = __roundup_pow_of_two(nr_irqs);
+		order = ilog2(nr_irqs);
+	}
+
+	guard(raw_spinlock_irqsave)(&ird_table->lock);
+	bitmap_release_region(ird_table->bitmap, index, order);
+}
+
 static void redirect_table_free(struct redirect_item *item)
 {
 	struct redirect_table *ird_table = &item->irde->ird_table;
@@ -324,6 +338,7 @@ static int redirect_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	index = redirect_table_alloc(node, nr_irqs);
 	if (index < 0) {
 		pr_err("Alloc redirect table entry failed\n");
+		irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 		return -EINVAL;
 	}
 
@@ -347,6 +362,7 @@ static int redirect_domain_alloc(struct irq_domain *domain, unsigned int virq,
 		item->gpid = kzalloc_node(sizeof(*item->gpid), GFP_KERNEL, node);
 		if (!item->gpid) {
 			pr_err("Alloc redirect GPID failed\n");
+			kfree(item);
 			goto out_free_resources;
 		}
 		item->index = index + i;
@@ -361,6 +377,7 @@ static int redirect_domain_alloc(struct irq_domain *domain, unsigned int virq,
 
 out_free_resources:
 	redirect_free_resources(domain, virq, nr_irqs);
+	redirect_table_free_region(node, index, nr_irqs);
 	irq_domain_free_irqs_common(domain, virq, nr_irqs);
 
 	return -ENOMEM;
@@ -436,8 +453,8 @@ static void redirect_irde_cfg(struct redirect_desc *irde)
 
 static void __init redirect_irde_free(struct redirect_desc *irde)
 {
-	struct redirect_table *ird_table = &redirect_descs->ird_table;
-	struct redirect_queue *inv_queue = &redirect_descs->inv_queue;
+	struct redirect_table *ird_table = &irde->ird_table;
+	struct redirect_queue *inv_queue = &irde->inv_queue;
 
 	if (ird_table->table) {
 		folio_put(virt_to_folio(ird_table->table));
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 01/16] irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
  2026-07-14 12:23   ` Haofeng Li
@ 2026-07-14 13:15     ` Anup Patel
  -1 siblings, 0 replies; 25+ messages in thread
From: Anup Patel @ 2026-07-14 13:15 UTC (permalink / raw)
  To: Haofeng Li
  Cc: tglx, linux-kernel, Haofeng Li, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Björn Töpel, linux-riscv

On Tue, Jul 14, 2026 at 5:54 PM Haofeng Li <lihaofeng@kylinos.cn> wrote:
>
> The MSI page lookup loop uses:
>
>         for (j = 0; nr_mmios; j++)
>
> When nr_mmios is non-zero the condition is always true, so j is never
> bounded. If reloff does not fall in any MMIO region the loop indexes
> past mmios[] and may hang or fault.

It is indeed an ugly typo in for-loop. I guess on most platforms
with AIA the below "if (reloff < resource_size(&mmios[j])) {" takes
care of loop termination but we can't rely on it.

>
> Also, mmios_va starts as NULL. If its allocation fails, the out_iounmap
> path indexes mmios_va[i] and NULL-dereferences.
>
> Bound the loop with j < nr_mmios, and guard the iounmap/kfree cleanup
> with if (mmios_va).
>
> Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Thanks,
Anup

> ---
>  drivers/irqchip/irq-riscv-imsic-state.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> index b8d1bbbf42f7..19f74cf79988 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.c
> +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> @@ -896,7 +896,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>                 index = nr_mmios;
>                 reloff = i * BIT(global->guest_index_bits) *
>                          IMSIC_MMIO_PAGE_SZ;
> -               for (j = 0; nr_mmios; j++) {
> +               for (j = 0; j < nr_mmios; j++) {
>                         if (reloff < resource_size(&mmios[j])) {
>                                 index = j;
>                                 break;
> @@ -953,11 +953,13 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>  out_local_cleanup:
>         imsic_local_cleanup();
>  out_iounmap:
> -       for (i = 0; i < nr_mmios; i++) {
> -               if (mmios_va[i])
> -                       iounmap(mmios_va[i]);
> +       if (mmios_va) {
> +               for (i = 0; i < nr_mmios; i++) {
> +                       if (mmios_va[i])
> +                               iounmap(mmios_va[i]);
> +               }
> +               kfree(mmios_va);
>         }
> -       kfree(mmios_va);
>         kfree(mmios);
>  out_free_local:
>         free_percpu(imsic->global.local);
> --
> 2.25.1
>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 01/16] irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup
@ 2026-07-14 13:15     ` Anup Patel
  0 siblings, 0 replies; 25+ messages in thread
From: Anup Patel @ 2026-07-14 13:15 UTC (permalink / raw)
  To: Haofeng Li
  Cc: tglx, linux-kernel, Haofeng Li, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Björn Töpel, linux-riscv

On Tue, Jul 14, 2026 at 5:54 PM Haofeng Li <lihaofeng@kylinos.cn> wrote:
>
> The MSI page lookup loop uses:
>
>         for (j = 0; nr_mmios; j++)
>
> When nr_mmios is non-zero the condition is always true, so j is never
> bounded. If reloff does not fall in any MMIO region the loop indexes
> past mmios[] and may hang or fault.

It is indeed an ugly typo in for-loop. I guess on most platforms
with AIA the below "if (reloff < resource_size(&mmios[j])) {" takes
care of loop termination but we can't rely on it.

>
> Also, mmios_va starts as NULL. If its allocation fails, the out_iounmap
> path indexes mmios_va[i] and NULL-dereferences.
>
> Bound the loop with j < nr_mmios, and guard the iounmap/kfree cleanup
> with if (mmios_va).
>
> Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Thanks,
Anup

> ---
>  drivers/irqchip/irq-riscv-imsic-state.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> index b8d1bbbf42f7..19f74cf79988 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.c
> +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> @@ -896,7 +896,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>                 index = nr_mmios;
>                 reloff = i * BIT(global->guest_index_bits) *
>                          IMSIC_MMIO_PAGE_SZ;
> -               for (j = 0; nr_mmios; j++) {
> +               for (j = 0; j < nr_mmios; j++) {
>                         if (reloff < resource_size(&mmios[j])) {
>                                 index = j;
>                                 break;
> @@ -953,11 +953,13 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>  out_local_cleanup:
>         imsic_local_cleanup();
>  out_iounmap:
> -       for (i = 0; i < nr_mmios; i++) {
> -               if (mmios_va[i])
> -                       iounmap(mmios_va[i]);
> +       if (mmios_va) {
> +               for (i = 0; i < nr_mmios; i++) {
> +                       if (mmios_va[i])
> +                               iounmap(mmios_va[i]);
> +               }
> +               kfree(mmios_va);
>         }
> -       kfree(mmios_va);
>         kfree(mmios);
>  out_free_local:
>         free_percpu(imsic->global.local);
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 03/16] irqchip/sifive-plic: do not iounmap devm mappings
  2026-07-14 12:23 ` Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  -1 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: Haofeng Li, Haibo Xu, Anup Patel, Rafael J. Wysocki, linux-kernel,
	Samuel Holland, Paul Walmsley, Haofeng Li, linux-riscv

From: Haofeng Li <lihaofeng@kylinos.cn>

plic_probe() maps registers with of_iomap() on the OF path, but with
devm_platform_ioremap_resource() on the ACPI/platform path.
fail_free_regs always calls iounmap(regs), which double-unmaps managed
mappings on the non-OF path.

Only call iounmap(regs) when the fwnode is an OF node.

Fixes: 206dd13a1011 ("irqchip/sifive-plic: Add ACPI support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-sifive-plic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 5b0dac104814..0bddad388741 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -819,7 +819,9 @@ static int plic_probe(struct fwnode_handle *fwnode)
 fail_free_priv:
 	kfree(priv);
 fail_free_regs:
-	iounmap(regs);
+	/* Only OF path uses of_iomap(); ACPI/platform uses devm mapping. */
+	if (is_of_node(fwnode))
+		iounmap(regs);
 	return error;
 }
 
-- 
2.25.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 03/16] irqchip/sifive-plic: do not iounmap devm mappings
@ 2026-07-14 13:24   ` Haofeng Li
  0 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Paul Walmsley,
	Samuel Holland, Haibo Xu, Anup Patel, Rafael J. Wysocki,
	Sunil V L, linux-riscv

From: Haofeng Li <lihaofeng@kylinos.cn>

plic_probe() maps registers with of_iomap() on the OF path, but with
devm_platform_ioremap_resource() on the ACPI/platform path.
fail_free_regs always calls iounmap(regs), which double-unmaps managed
mappings on the non-OF path.

Only call iounmap(regs) when the fwnode is an OF node.

Fixes: 206dd13a1011 ("irqchip/sifive-plic: Add ACPI support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-sifive-plic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 5b0dac104814..0bddad388741 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -819,7 +819,9 @@ static int plic_probe(struct fwnode_handle *fwnode)
 fail_free_priv:
 	kfree(priv);
 fail_free_regs:
-	iounmap(regs);
+	/* Only OF path uses of_iomap(); ACPI/platform uses devm mapping. */
+	if (is_of_node(fwnode))
+		iounmap(regs);
 	return error;
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 04/16] irqchip/crossbar: fix allocation and init cleanup
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 13:24   ` [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths Haofeng Li
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Jason Cooper, Marc Zyngier,
	Tony Lindgren

From: Haofeng Li <lihaofeng@kylinos.cn>

crossbar_domain_alloc() returns in the middle of a multi-IRQ
allocation without freeing IRQs and crossbar slots allocated by
earlier iterations.

If irq_domain_create_hierarchy() fails after crossbar_of_init(), the
global crossbar object and its maps and MMIO mapping are also leaked.

Roll back prior IRQs through crossbar_domain_free(), and release all
crossbar resources when domain creation fails.

Fixes: 783d31863fb8 ("irqchip: crossbar: Convert dra7 crossbar to stacked domains")

Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-crossbar.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index 033b08782119..0ac5268aa8e4 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -42,6 +42,9 @@ struct crossbar_device {
 
 static struct crossbar_device *cb;
 
+static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
+				 unsigned int nr_irqs);
+
 static void crossbar_writel(int irq_no, int cb_no)
 {
 	writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
@@ -127,11 +130,14 @@ static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
 	for (i = 0; i < nr_irqs; i++) {
 		int err = allocate_gic_irq(d, virq + i, hwirq + i);
 
-		if (err)
+		if (err) {
+			if (i)
+				crossbar_domain_free(d, virq, i);
 			return err;
+		}
 
 		irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
-					      &crossbar_chip, NULL);
+					     &crossbar_chip, NULL);
 	}
 
 	return 0;
@@ -336,6 +342,18 @@ static int __init crossbar_of_init(struct device_node *node)
 	return ret;
 }
 
+static void __init crossbar_free(void)
+{
+	if (!cb)
+		return;
+
+	kfree(cb->register_offsets);
+	kfree(cb->irq_map);
+	iounmap(cb->crossbar_base);
+	kfree(cb);
+	cb = NULL;
+}
+
 static int __init irqcrossbar_init(struct device_node *node,
 				   struct device_node *parent)
 {
@@ -361,6 +379,7 @@ static int __init irqcrossbar_init(struct device_node *node,
 					     of_fwnode_handle(node), &crossbar_domain_ops, NULL);
 	if (!domain) {
 		pr_err("%pOF: failed to allocated domain\n", node);
+		crossbar_free();
 		return -ENOMEM;
 	}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 05/16] irqchip/bcm7038-l1: clean up init failure paths
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
  2026-07-14 13:24   ` [PATCH 04/16] irqchip/crossbar: fix allocation and init cleanup Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 13:24   ` [PATCH 06/16] irqchip/loongson-liointc: unmap per-core iomaps on error Haofeng Li
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ 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 04/16] irqchip/crossbar: fix allocation and init cleanup Haofeng Li
  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-07-14 13:24   ` [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure Haofeng Li
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (2 preceding siblings ...)
  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-07-14 13:24   ` [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails Haofeng Li
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* [PATCH 08/16] irqchip/mips-gic: clean up if IPI domain registration fails
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (3 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-07-14 13:24   ` [PATCH 09/16] irqchip/econet: clean up VEIC initialization Haofeng Li
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* [PATCH 09/16] irqchip/econet: clean up VEIC initialization
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (4 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-14 13:24   ` [PATCH 10/16] irqchip/aspeed-vic: publish handler only after domain creation Haofeng Li
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* [PATCH 10/16] irqchip/aspeed-vic: publish handler only after domain creation
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (5 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 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure Haofeng Li
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Joel Stanley,
	Andrew Jeffery, Jason Cooper, Benjamin Herrenschmidt,
	linux-arm-kernel, linux-aspeed

From: Haofeng Li <lihaofeng@kylinos.cn>

avic_of_init() publishes system_avic and installs the root IRQ
handler before creating the IRQ domain, then returns success even if
irq_domain_create_simple() fails.

Freeing the VIC after the root handler has been installed would leave
avic_handle_irq() pointing at a cleared or freed controller. Create
the domain first, then publish the controller and install the handler.
Also handle set_handle_irq() failure by removing the domain and
releasing all resources before the handler has been changed.

Fixes: 5952884258e5 ("irqchip/aspeed-vic: Add irq controller for Aspeed")

Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-aspeed-vic.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
index 6649b893f39c..bb3cceec375f 100644
--- a/drivers/irqchip/irq-aspeed-vic.c
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -186,6 +186,7 @@ static int __init avic_of_init(struct device_node *node,
 {
 	void __iomem *regs;
 	struct aspeed_vic *vic;
+	int ret;
 
 	if (WARN(parent, "non-root Aspeed VIC not supported"))
 		return -EINVAL;
@@ -206,15 +207,29 @@ static int __init avic_of_init(struct device_node *node,
 	/* Initialize sources, all masked */
 	vic_init_hw(vic);
 
-	/* Ready to receive interrupts */
-	system_avic = vic;
-	set_handle_irq(avic_handle_irq);
-
 	/* Register our domain */
 	vic->dom = irq_domain_create_simple(of_fwnode_handle(node), NUM_IRQS, 0,
 					    &avic_dom_ops, vic);
+	if (!vic->dom) {
+		ret = -ENOMEM;
+		goto err_free_vic;
+	}
+
+	/* Ready to receive interrupts */
+	system_avic = vic;
+	ret = set_handle_irq(avic_handle_irq);
+	if (ret)
+		goto err_remove_domain;
 
 	return 0;
+
+err_remove_domain:
+	system_avic = NULL;
+	irq_domain_remove(vic->dom);
+err_free_vic:
+	iounmap(regs);
+	kfree(vic);
+	return ret;
 }
 
 IRQCHIP_DECLARE(ast2400_vic, "aspeed,ast2400-vic", avic_of_init);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (6 preceding siblings ...)
  2026-07-14 13:24   ` [PATCH 10/16] irqchip/aspeed-vic: publish handler only after domain creation Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 13:24   ` [PATCH 12/16] irqchip/realtek-rtl: unmap per-CPU bases on init failure Haofeng Li
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* [PATCH 12/16] irqchip/realtek-rtl: unmap per-CPU bases on init failure
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (7 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-14 13:24   ` [PATCH 13/16] irqchip/realtek-rtl: dispose parent mapping on domain failure Haofeng Li
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx; +Cc: linux-kernel, Haofeng Li, Haofeng Li, Markus Stockhausen

From: Haofeng Li <lihaofeng@kylinos.cn>

realtek_rtl_of_init() maps a separate register base for every present
CPU. If mapping CPU n fails, mappings for earlier CPUs remain. Parent
IRQ lookup and domain creation failures also leave all per-CPU mappings
allocated.

Add realtek_rtl_unmap_bases() and use it on every error path after
mapping starts.

Fixes: a1a35c09241f ("irqchip/irq-realtek-rtl: Add multicore support")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-realtek-rtl.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 2ae3be7fa633..1f1dfa6e3d84 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -147,6 +147,18 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
+static void __init realtek_rtl_unmap_bases(void)
+{
+	int cpu;
+
+	for_each_present_cpu(cpu) {
+		if (realtek_ictl_base[cpu]) {
+			iounmap(realtek_ictl_base[cpu]);
+			realtek_ictl_base[cpu] = NULL;
+		}
+	}
+}
+
 static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
 {
 	struct of_phandle_args oirq;
@@ -155,8 +167,10 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
 
 	for_each_present_cpu(cpu) {
 		realtek_ictl_base[cpu] = of_iomap(node, cpu);
-		if (!realtek_ictl_base[cpu])
+		if (!realtek_ictl_base[cpu]) {
+			realtek_rtl_unmap_bases();
 			return -ENXIO;
+		}
 
 		/* Disable all cascaded interrupts and clear routing */
 		for (unsigned int hw_irq = 0; hw_irq < RTL_ICTL_NUM_INPUTS; hw_irq++) {
@@ -183,14 +197,19 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
 		parent_irq = of_irq_get(node, 0);
 	}
 
-	if (parent_irq < 0)
+	if (parent_irq < 0) {
+		realtek_rtl_unmap_bases();
 		return parent_irq;
-	else if (!parent_irq)
+	} else if (!parent_irq) {
+		realtek_rtl_unmap_bases();
 		return -ENODEV;
+	}
 
 	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS, &irq_domain_ops, NULL);
-	if (!domain)
+	if (!domain) {
+		realtek_rtl_unmap_bases();
 		return -ENOMEM;
+	}
 
 	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, domain);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 13/16] irqchip/realtek-rtl: dispose parent mapping on domain failure
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (8 preceding siblings ...)
  2026-07-14 13:24   ` [PATCH 12/16] irqchip/realtek-rtl: unmap per-CPU bases on init failure Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 13:24   ` [PATCH 14/16] irqchip/renesas-rzg2l: fix wrong errno in reset error log Haofeng Li
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx; +Cc: linux-kernel, Haofeng Li, Haofeng Li, Sander Vanheule,
	Marc Zyngier

From: Haofeng Li <lihaofeng@kylinos.cn>

If irq_domain_create_linear() fails after mapping the parent interrupt,
the parent IRQ mapping remains allocated.

Dispose the parent mapping before returning the error.

Fixes: 9070f1ce31c5 ("irqchip/realtek-rtl: use parent interrupts")
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-realtek-rtl.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 1f1dfa6e3d84..c20559591074 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -207,6 +207,7 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
 
 	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS, &irq_domain_ops, NULL);
 	if (!domain) {
+		irq_dispose_mapping(parent_irq);
 		realtek_rtl_unmap_bases();
 		return -ENOMEM;
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 14/16] irqchip/renesas-rzg2l: fix wrong errno in reset error log
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (9 preceding siblings ...)
  2026-07-14 13:24   ` [PATCH 13/16] irqchip/realtek-rtl: dispose parent mapping on domain failure Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 13:24   ` [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails Haofeng Li
  2026-07-14 13:24   ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li
  12 siblings, 0 replies; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Philipp Zabel,
	Lad Prabhakar, Fabrizio Castro

From: Haofeng Li <lihaofeng@kylinos.cn>

Commit 78f384dad082 ("irqchip/renesas-rzg2l: Use
devm_reset_control_get_exclusive_deasserted()") added an error message
for reset control acquisition failure, but it prints ret from a
previous successful call instead of PTR_ERR(resetn).

Drop the stale format argument. dev_err_probe() already reports the
error passed as its second argument symbolically.

Fixes: 78f384dad082 ("irqchip/renesas-rzg2l: Use devm_reset_control_get_exclusive_deasserted()")

Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-renesas-rzg2l.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index f6b2e69a2f4e..c37e7fce6248 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -863,7 +863,7 @@ static int rzg2l_irqc_common_probe(struct platform_device *pdev, struct device_n
 	resetn = devm_reset_control_get_exclusive_deasserted(dev, NULL);
 	if (IS_ERR(resetn)) {
 		return dev_err_probe(dev, PTR_ERR(resetn),
-				     "failed to acquire deasserted reset: %d\n", ret);
+				     "failed to acquire deasserted reset\n");
 	}
 
 	ret = devm_pm_runtime_enable(dev);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (10 preceding siblings ...)
  2026-07-14 13:24   ` [PATCH 14/16] irqchip/renesas-rzg2l: fix wrong errno in reset error log Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  2026-07-14 14:53     ` Marc Zyngier
  2026-07-14 13:24   ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li
  12 siblings, 1 reply; 25+ messages in thread
From: Haofeng Li @ 2026-07-14 13:24 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, Haofeng Li, Haofeng Li, Marc Zyngier, Sudeep Holla,
	Vikram Sethi, Shanker Donthineni, linux-arm-kernel

From: Haofeng Li <lihaofeng@kylinos.cn>

NVIDIA T241 GICD alias setup only warns about a failed ioremap, then
enables gic_nvidia_t241_erratum. Later accesses through the missing
alias can dereference NULL.

If any alias cannot be mapped, report which chip failed, unmap all
aliases created so far, and return without enabling the erratum static
key.

Fixes: 35727af2b15d ("irqchip/gicv3: Workaround for NVIDIA erratum T241-FABRIC-4")

Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
---
 drivers/irqchip/irq-gic-v3.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 99444a1b2ffa..a8a395a98c09 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1840,7 +1840,16 @@ static bool gic_enable_quirk_nvidia_t241(void *data)
 			phys = gic_data.dist_phys_base + T241_CHIP_GICDA_OFFSET;
 			phys |= FIELD_PREP(T241_CHIPN_MASK, i);
 			t241_dist_base_alias[i] = ioremap(phys, SZ_64K);
-			WARN_ON_ONCE(!t241_dist_base_alias[i]);
+			if (!t241_dist_base_alias[i]) {
+				pr_err("Failed to map NVIDIA T241 GICD alias for chip %u\n", i);
+				while (i--) {
+					if (t241_dist_base_alias[i]) {
+						iounmap(t241_dist_base_alias[i]);
+						t241_dist_base_alias[i] = NULL;
+					}
+				}
+				return false;
+			}
 		}
 	}
 	static_branch_enable(&gic_nvidia_t241_erratum);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling
       [not found] ` <20260714132453.3302672-1-920484857@qq.com>
                     ` (11 preceding siblings ...)
  2026-07-14 13:24   ` [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails Haofeng Li
@ 2026-07-14 13:24   ` Haofeng Li
  12 siblings, 0 replies; 25+ 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] 25+ messages in thread

* Re: [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails
  2026-07-14 13:24   ` [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails Haofeng Li
@ 2026-07-14 14:53     ` Marc Zyngier
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Zyngier @ 2026-07-14 14:53 UTC (permalink / raw)
  To: Haofeng Li
  Cc: tglx, linux-kernel, Haofeng Li, Haofeng Li, Sudeep Holla,
	Vikram Sethi, Shanker Donthineni, linux-arm-kernel

On Tue, 14 Jul 2026 14:24:51 +0100,
Haofeng Li <920484857@qq.com> wrote:
> 
> From: Haofeng Li <lihaofeng@kylinos.cn>
> 
> NVIDIA T241 GICD alias setup only warns about a failed ioremap, then
> enables gic_nvidia_t241_erratum. Later accesses through the missing
> alias can dereference NULL.

There won't be any later accesses, the machine is *dead*, short of
reliably handle interrupts. The only thing this patch is doing is
giving a false sense of having fixed something, while it is far worse
than the existing situation.

Please tell that to your LLM.

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 03/16] irqchip/sifive-plic: do not iounmap devm mappings
  2026-07-14 13:24   ` Haofeng Li
@ 2026-07-14 15:05     ` Anup Patel
  -1 siblings, 0 replies; 25+ messages in thread
From: Anup Patel @ 2026-07-14 15:05 UTC (permalink / raw)
  To: Haofeng Li
  Cc: tglx, linux-kernel, Haofeng Li, Haofeng Li, Paul Walmsley,
	Samuel Holland, Haibo Xu, Rafael J. Wysocki, Sunil V L,
	linux-riscv

On Tue, Jul 14, 2026 at 6:56 PM Haofeng Li <920484857@qq.com> wrote:
>
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> plic_probe() maps registers with of_iomap() on the OF path, but with
> devm_platform_ioremap_resource() on the ACPI/platform path.
> fail_free_regs always calls iounmap(regs), which double-unmaps managed
> mappings on the non-OF path.

devm_platform_ioremap_resource() can't be used for OF because
we have one outlier platform "allwinner,sun20i-d1-plic" which still
relies on early irqchip probe using IRQCHIP_DECLARE() and
the platform device is not available in early irqchip probe.

>
> Only call iounmap(regs) when the fwnode is an OF node.
>
> Fixes: 206dd13a1011 ("irqchip/sifive-plic: Add ACPI support")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Thanks,
Anup


> --
>  drivers/irqchip/irq-sifive-plic.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> index 5b0dac104814..0bddad388741 100644
> --- a/drivers/irqchip/irq-sifive-plic.c
> +++ b/drivers/irqchip/irq-sifive-plic.c
> @@ -819,7 +819,9 @@ static int plic_probe(struct fwnode_handle *fwnode)
>  fail_free_priv:
>         kfree(priv);
>  fail_free_regs:
> -       iounmap(regs);
> +       /* Only OF path uses of_iomap(); ACPI/platform uses devm mapping. */
> +       if (is_of_node(fwnode))
> +               iounmap(regs);
>         return error;
>  }
>
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 03/16] irqchip/sifive-plic: do not iounmap devm mappings
@ 2026-07-14 15:05     ` Anup Patel
  0 siblings, 0 replies; 25+ messages in thread
From: Anup Patel @ 2026-07-14 15:05 UTC (permalink / raw)
  To: Haofeng Li
  Cc: Samuel Holland, Haibo Xu, Rafael J. Wysocki, linux-kernel,
	Haofeng Li, tglx, Paul Walmsley, Haofeng Li, linux-riscv

On Tue, Jul 14, 2026 at 6:56 PM Haofeng Li <920484857@qq.com> wrote:
>
> From: Haofeng Li <lihaofeng@kylinos.cn>
>
> plic_probe() maps registers with of_iomap() on the OF path, but with
> devm_platform_ioremap_resource() on the ACPI/platform path.
> fail_free_regs always calls iounmap(regs), which double-unmaps managed
> mappings on the non-OF path.

devm_platform_ioremap_resource() can't be used for OF because
we have one outlier platform "allwinner,sun20i-d1-plic" which still
relies on early irqchip probe using IRQCHIP_DECLARE() and
the platform device is not available in early irqchip probe.

>
> Only call iounmap(regs) when the fwnode is an OF node.
>
> Fixes: 206dd13a1011 ("irqchip/sifive-plic: Add ACPI support")
> Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Thanks,
Anup


> --
>  drivers/irqchip/irq-sifive-plic.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> index 5b0dac104814..0bddad388741 100644
> --- a/drivers/irqchip/irq-sifive-plic.c
> +++ b/drivers/irqchip/irq-sifive-plic.c
> @@ -819,7 +819,9 @@ static int plic_probe(struct fwnode_handle *fwnode)
>  fail_free_priv:
>         kfree(priv);
>  fail_free_regs:
> -       iounmap(regs);
> +       /* Only OF path uses of_iomap(); ACPI/platform uses devm mapping. */
> +       if (is_of_node(fwnode))
> +               iounmap(regs);
>         return error;
>  }
>
> --
> 2.25.1
>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-07-14 15:06 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 12:23 [PATCH 00/16] irqchip: harden initialization error paths Haofeng Li
2026-07-14 12:23 ` Haofeng Li
2026-07-14 12:23 ` [PATCH 01/16] irqchip/riscv-imsic: fix MMIO lookup OOB and NULL cleanup Haofeng Li
2026-07-14 12:23   ` Haofeng Li
2026-07-14 13:15   ` Anup Patel
2026-07-14 13:15     ` Anup Patel
2026-07-14 12:23 ` [PATCH 02/16] irqchip/loongarch-ir: fix redirect free and alloc leaks Haofeng Li
2026-07-14 13:24 ` [PATCH 03/16] irqchip/sifive-plic: do not iounmap devm mappings Haofeng Li
2026-07-14 13:24   ` Haofeng Li
2026-07-14 15:05   ` Anup Patel
2026-07-14 15:05     ` Anup Patel
     [not found] ` <20260714132453.3302672-1-920484857@qq.com>
2026-07-14 13:24   ` [PATCH 04/16] irqchip/crossbar: fix allocation and init cleanup Haofeng Li
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   ` [PATCH 07/16] irqchip/mips-gic: clean up IRQ domain creation failure Haofeng Li
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   ` [PATCH 09/16] irqchip/econet: clean up VEIC initialization Haofeng Li
2026-07-14 13:24   ` [PATCH 10/16] irqchip/aspeed-vic: publish handler only after domain creation Haofeng Li
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 12/16] irqchip/realtek-rtl: unmap per-CPU bases on init failure Haofeng Li
2026-07-14 13:24   ` [PATCH 13/16] irqchip/realtek-rtl: dispose parent mapping on domain failure Haofeng Li
2026-07-14 13:24   ` [PATCH 14/16] irqchip/renesas-rzg2l: fix wrong errno in reset error log Haofeng Li
2026-07-14 13:24   ` [PATCH 15/16] irqchip/gic-v3: fail T241 quirk if alias ioremap fails Haofeng Li
2026-07-14 14:53     ` Marc Zyngier
2026-07-14 13:24   ` [PATCH 16/16] irqchip/bcm7120-l2: fix parent IRQ count error handling Haofeng Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.