[PATCH 7/7] irqchip/irq-realtek-rtl: Activate multiple parents

From: Markus Stockhausen

Date: Fri Jun 05 2026 - 17:19:13 EST


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@xxxxxx>
---
drivers/irqchip/irq-realtek-rtl.c | 88 +++++++++++++++++--------------
1 file changed, 48 insertions(+), 40 deletions(-)

diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c
index 5c5097edbc98..4b59e0cd86bf 100644
--- a/drivers/irqchip/irq-realtek-rtl.c
+++ b/drivers/irqchip/irq-realtek-rtl.c
@@ -175,64 +175,72 @@ static void realtek_irq_dispatch(struct irq_desc *desc)

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;
--
2.54.0