[PATCH 12/16] irqchip/realtek-rtl: unmap per-CPU bases on init failure

From: Haofeng Li

Date: Tue Jul 14 2026 - 09:30:43 EST


From: Haofeng Li <lihaofeng@xxxxxxxxxx>

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@xxxxxxxxxx>
---
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