From 3031d8f878219f446330088193d799a3e67122d5 Mon Sep 17 00:00:00 2001
From: Markus Stockhausen <markus.stockhausen@gmx.de>
Date: Fri, 5 Jun 2026 20:49:47 +0200
Subject: [PATCH 8/8] irqchip/irq-realtek-rtl: Activate multiple parents

Until now the driver exactly registers a single parent interrupt.
Relax this to make use of all defined interrupts in the device tree.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/irqchip/irq-realtek-rtl.c | 88 +++++++++++++++++--------------
 1 file changed, 48 insertions(+), 40 deletions(-)

--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -175,64 +175,72 @@ out:
 
 static int __init realtek_setup_parents(struct device_node *node)
 {
-	int err, parent_irq, num_parents = of_irq_count(node);
+	int p, cnt, err, parent_irq, num_parents = of_irq_count(node);
 	struct realtek_ictl_output *output;
 	struct irq_data *parent_data;
 	struct of_phandle_args oirq;
 	struct irq_domain *domain;
 
-	output = kcalloc(1, sizeof(*output), GFP_KERNEL);
+	cnt = max(1, num_parents);
+	output = kcalloc(cnt, sizeof(*output), GFP_KERNEL);
 	if (!output)
 		return -ENOMEM;
 
-	if (WARN_ON(!num_parents)) {
-		/*
-		 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
-		 * connected to the first output. This is the case for all known hardware.
-		 */
-		oirq.np = of_find_compatible_node(NULL, NULL,
-						  "mti,cpu-interrupt-controller");
-		if (!oirq.np) {
-			err = -EINVAL;
-			goto err_out;
+	for (p = 0; p < cnt; p++) {
+		if (WARN_ON(!num_parents)) {
+			/*
+			 * If DT contains no parent interrupts, assume MIPS IRQ 2 (HW0) is
+			 * connected to the first output. This is the case for all known hardware.
+			 */
+			oirq.np = of_find_compatible_node(NULL, NULL,
+							  "mti,cpu-interrupt-controller");
+			if (!oirq.np) {
+				err = -EINVAL;
+				goto err_out;
+			}
+
+			oirq.args_count = 1;
+			oirq.args[0] = 2;
+			parent_irq = irq_create_of_mapping(&oirq);
+			of_node_put(oirq.np);
+		} else {
+			parent_irq = of_irq_get(node, p);
 		}
 
-		oirq.args_count = 1;
-		oirq.args[0] = 2;
-		parent_irq = irq_create_of_mapping(&oirq);
-		of_node_put(oirq.np);
-	} else {
-		parent_irq = of_irq_get(node, 0);
-	}
+		if (parent_irq <= 0) {
+			err = parent_irq ? parent_irq : -ENODEV;
+			goto err_out;
+		}
 
-	if (parent_irq <= 0) {
-		err = parent_irq ? parent_irq : -ENODEV;
-		goto err_out;
-	}
+		parent_data = irq_get_irq_data(parent_irq);
+		if (!parent_data) {
+			err = -EINVAL;
+			goto err_out;
+		}
 
-	parent_data = irq_get_irq_data(parent_irq);
-	if (!parent_data) {
-		err = -EINVAL;
-		goto err_out;
-	}
+		domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
+						  &irq_domain_ops, &output[p]);
+		if (!domain) {
+			err = -ENOMEM;
+			goto err_out;
+		}
 
-	domain = irq_domain_create_linear(of_fwnode_handle(node), RTL_ICTL_NUM_INPUTS,
-					  &irq_domain_ops, output);
-	if (!domain) {
-		err = -ENOMEM;
-		goto err_out;
+		output[p].domain = domain;
+		output[p].fwnode = of_fwnode_handle(node);
+		output[p].index = p;
+		output[p].parent_irq = parent_irq;
+		output[p].parent_hwirq = irqd_to_hwirq(parent_data);
+		irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, &output[p]);
 	}
 
-	output->domain = domain;
-	output->fwnode = of_fwnode_handle(node);
-	output->index = 0;
-	output->parent_irq = parent_irq;
-	output->parent_hwirq = irqd_to_hwirq(parent_data);
-	irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, output);
-
 	return 0;
 
 err_out:
+	while (p--) {
+		irq_set_chained_handler_and_data(output[p].parent_irq, NULL, NULL);
+		irq_domain_remove(output[p].domain);
+	}
+
 	kfree(output);
 
 	return err;
