Browse Source

of/irq: Fix bug in interrupt parsing refactor.

Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced
a bug. The irq parsing will fail for some nodes that don't have a reg
property. It is fixed by deferring the check for reg until it is
actually needed. Also adjust the testcase data to catch the bug.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Tested-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Ming Lei <tom.leiming@gmail.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Grant Likely 11 years ago
parent
commit
78119fd106
2 changed files with 14 additions and 13 deletions
  1. 4 3
      arch/arm/boot/dts/testcases/tests-interrupts.dtsi
  2. 10 10
      drivers/of/irq.c

+ 4 - 3
arch/arm/boot/dts/testcases/tests-interrupts.dtsi

@@ -2,7 +2,8 @@
 / {
 	testcase-data {
 		interrupts {
-			#address-cells = <0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			test_intc0: intc0 {
 				interrupt-controller;
 				#interrupt-cells = <1>;
@@ -29,8 +30,7 @@
 
 			test_intmap1: intmap1 {
 				#interrupt-cells = <2>;
-				#address-cells = <0>;
-				interrupt-map = <1 2 &test_intc0 15>;
+				interrupt-map = <0x5000 1 2 &test_intc0 15>;
 			};
 
 			interrupts0 {
@@ -44,6 +44,7 @@
 			};
 
 			interrupts-extended0 {
+				reg = <0x5000 0x100>;
 				interrupts-extended = <&test_intc0 1>,
 						      <&test_intc1 2 3 4>,
 						      <&test_intc2 5 6>,

+ 10 - 10
drivers/of/irq.c

@@ -147,18 +147,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 
 	pr_debug(" -> addrsize=%d\n", addrsize);
 
-	/* If we were passed no "reg" property and we attempt to parse
-	 * an interrupt-map, then #address-cells must be 0.
-	 * Fail if it's not.
-	 */
-	if (addr == NULL && addrsize != 0) {
-		pr_debug(" -> no reg passed in when needed !\n");
-		return -EINVAL;
-	}
-
 	/* Precalculate the match array - this simplifies match loop */
 	for (i = 0; i < addrsize; i++)
-		initial_match_array[i] = addr[i];
+		initial_match_array[i] = addr ? addr[i] : 0;
 	for (i = 0; i < intsize; i++)
 		initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
 
@@ -174,6 +165,15 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 			return 0;
 		}
 
+		/*
+		 * interrupt-map parsing does not work without a reg
+		 * property when #address-cells != 0
+		 */
+		if (addrsize && !addr) {
+			pr_debug(" -> no reg passed in when needed !\n");
+			goto fail;
+		}
+
 		/* Now look for an interrupt-map */
 		imap = of_get_property(ipar, "interrupt-map", &imaplen);
 		/* No interrupt map, check for an interrupt parent */