diff mbox series

[v1,2/3] realtek: backport SoC IRQ off-by-one fix

Message ID acaf8fd272c91b14c917d3996af0f5d9001c9a4a.1644763292.git.sander@svanheule.net
State Changes Requested
Headers show
Series realtek: backport SoC interrupt fixes | expand

Commit Message

Sander Vanheule Feb. 13, 2022, 2:42 p.m. UTC
The off-by-one error in the interrupt routing table caused the interrupt
handlers to be attached to the wrong parent interrupt, but this was
hidden by the fact that there was an unrelated interrupt routing for
every used interrupt.

The SoC DTS includes are updated to correctly reflect the SoC to CPU
interrupt routing.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
---
 target/linux/realtek/dts-5.10/rtl838x.dtsi    | 14 ++---
 target/linux/realtek/dts-5.10/rtl930x.dtsi    | 24 ++++----
 ...ealtek-rtl-fix-off-by-one-in-routing.patch | 60 +++++++++++++++++++
 3 files changed, 79 insertions(+), 19 deletions(-)
 create mode 100644 target/linux/realtek/patches-5.10/009-5.15.19-irqchip-realtek-rtl-fix-off-by-one-in-routing.patch
diff mbox series

Patch

diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi
index a5713748a9ea..50be0d8967c2 100644
--- a/target/linux/realtek/dts-5.10/rtl838x.dtsi
+++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi
@@ -94,13 +94,13 @@ 
 			#interrupt-cells = <1>;
 			interrupt-controller;
 			interrupt-map =
-				<31 &cpuintc 2>, /* UART0 */
-				<30 &cpuintc 1>, /* UART1 */
-				<24 &cpuintc 4>, /* NIC */
-				<23 &cpuintc 4>, /* GPIO_ABCD */
-				<20 &cpuintc 3>, /* SWCORE */
-				<19 &cpuintc 4>, /* WDT_IP1 */
-				<18 &cpuintc 5>; /* WDT_IP2 */
+				<31 &cpuintc 3>, /* UART0 */
+				<30 &cpuintc 2>, /* UART1 */
+				<24 &cpuintc 5>, /* NIC */
+				<23 &cpuintc 5>, /* GPIO_ABCD */
+				<20 &cpuintc 4>, /* SWCORE */
+				<19 &cpuintc 5>, /* WDT_IP1 */
+				<18 &cpuintc 6>; /* WDT_IP2 */
 		};
 
 		spi0: spi@1200 {
diff --git a/target/linux/realtek/dts-5.10/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi
index 38630bb6c26a..bce982739a13 100644
--- a/target/linux/realtek/dts-5.10/rtl930x.dtsi
+++ b/target/linux/realtek/dts-5.10/rtl930x.dtsi
@@ -99,18 +99,18 @@ 
 			#interrupt-cells = <1>;
 			interrupt-controller;
 			interrupt-map =
-				<31 &cpuintc 1>, /* UART1 */
-				<30 &cpuintc 2>, /* UART0 */
-				<24 &cpuintc 4>, /* NIC */
-				<23 &cpuintc 3>, /* SWCORE */
-				<13 &cpuintc 4>, /* GPIO_ABCD */
-				<11 &cpuintc 1>, /* TC4 */
-				<10 &cpuintc 1>, /* TC3 */
-				<9 &cpuintc 1>,  /* TC2 */
-				<8 &cpuintc 1>,  /* TC1 */
-				<7 &cpuintc 5>,  /* TC0 */
-				<6 &cpuintc 5>,  /* WDT_IP2 */
-				<5 &cpuintc 4>;  /* WDT_IP1 */
+				<31 &cpuintc 2>, /* UART1 */
+				<30 &cpuintc 3>, /* UART0 */
+				<24 &cpuintc 5>, /* NIC */
+				<23 &cpuintc 4>, /* SWCORE */
+				<13 &cpuintc 5>, /* GPIO_ABCD */
+				<11 &cpuintc 2>, /* TC4 */
+				<10 &cpuintc 2>, /* TC3 */
+				<9 &cpuintc 2>,  /* TC2 */
+				<8 &cpuintc 2>,  /* TC1 */
+				<7 &cpuintc 6>,  /* TC0 */
+				<6 &cpuintc 6>,  /* WDT_IP2 */
+				<5 &cpuintc 5>;  /* WDT_IP1 */
 		};
 
 		timer: timer@3200 {
diff --git a/target/linux/realtek/patches-5.10/009-5.15.19-irqchip-realtek-rtl-fix-off-by-one-in-routing.patch b/target/linux/realtek/patches-5.10/009-5.15.19-irqchip-realtek-rtl-fix-off-by-one-in-routing.patch
new file mode 100644
index 000000000000..4d194b682b4f
--- /dev/null
+++ b/target/linux/realtek/patches-5.10/009-5.15.19-irqchip-realtek-rtl-fix-off-by-one-in-routing.patch
@@ -0,0 +1,60 @@ 
+From 91351b5dd0fd494eb2d85e1bb6aca77b067447e0 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander@svanheule.net>
+Date: Sun, 9 Jan 2022 15:54:33 +0100
+Subject: irqchip/realtek-rtl: Fix off-by-one in routing
+
+From: Sander Vanheule <sander@svanheule.net>
+
+commit 91351b5dd0fd494eb2d85e1bb6aca77b067447e0 upstream.
+
+There is an offset between routing values (1..6) and the connected MIPS
+CPU interrupts (2..7), but no distinction was made between these two
+values.
+
+This issue was previously hidden during testing, because an interrupt
+mapping was used where for each required interrupt another (unused)
+routing was configured, with an offset of +1.
+
+Offset the CPU IRQ numbers by -1 to retrieve the correct routing value.
+
+Fixes: 9f3a0f34b84a ("irqchip: Add support for Realtek RTL838x/RTL839x interrupt controller")
+Signed-off-by: Sander Vanheule <sander@svanheule.net>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/177b920aa8d8610615692d0e657e509f363c85ca.1641739718.git.sander@svanheule.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-realtek-rtl.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/irqchip/irq-realtek-rtl.c
++++ b/drivers/irqchip/irq-realtek-rtl.c
+@@ -95,7 +95,8 @@ out:
+  * SoC interrupts are cascaded to MIPS CPU interrupts according to the
+  * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for
+  * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts
+- * thus go into 4 IRRs.
++ * thus go into 4 IRRs. A routing value of '0' means the interrupt is left
++ * disconnected. Routing values {1..15} connect to output lines {0..14}.
+  */
+ static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)
+ {
+@@ -134,7 +135,7 @@ static int __init map_interrupts(struct
+ 		of_node_put(cpu_ictl);
+ 
+ 		cpu_int = be32_to_cpup(imap + 2);
+-		if (cpu_int > 7)
++		if (cpu_int > 7 || cpu_int < 2)
+ 			return -EINVAL;
+ 
+ 		if (!(mips_irqs_set & BIT(cpu_int))) {
+@@ -143,7 +144,8 @@ static int __init map_interrupts(struct
+ 			mips_irqs_set |= BIT(cpu_int);
+ 		}
+ 
+-		regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32;
++		/* Use routing values (1..6) for CPU interrupts (2..7) */
++		regs[(soc_int * 4) / 32] |= (cpu_int - 1) << (soc_int * 4) % 32;
+ 		imap += 3;
+ 	}
+