aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@linaro.org>2013-11-01 13:50:50 -0400
committerShawn Guo <shawn.guo@freescale.com>2014-05-16 04:19:13 -0400
commit9c67477d3750f413e59e04c91abfbcd6076930a9 (patch)
tree8eade8e732bb6efcf141d4062dcbcb8485cc6ef2
parentbb976a3070d8f947dddbf738cfe36487ec17ab2a (diff)
ENGR00313685-10 of/irq: Fix bug in interrupt parsing refactor.
commit 78119fd1068cc068f6112a57a5f6de0e5b20245a upstream. 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> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
-rw-r--r--arch/arm/boot/dts/testcases/tests-interrupts.dtsi7
-rw-r--r--drivers/of/irq.c20
2 files changed, 14 insertions, 13 deletions
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
index 560d6bf680b6..c843720bd3e5 100644
--- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
@@ -2,7 +2,8 @@
2/ { 2/ {
3 testcase-data { 3 testcase-data {
4 interrupts { 4 interrupts {
5 #address-cells = <0>; 5 #address-cells = <1>;
6 #size-cells = <1>;
6 test_intc0: intc0 { 7 test_intc0: intc0 {
7 interrupt-controller; 8 interrupt-controller;
8 #interrupt-cells = <1>; 9 #interrupt-cells = <1>;
@@ -29,8 +30,7 @@
29 30
30 test_intmap1: intmap1 { 31 test_intmap1: intmap1 {
31 #interrupt-cells = <2>; 32 #interrupt-cells = <2>;
32 #address-cells = <0>; 33 interrupt-map = <0x5000 1 2 &test_intc0 15>;
33 interrupt-map = <1 2 &test_intc0 15>;
34 }; 34 };
35 35
36 interrupts0 { 36 interrupts0 {
@@ -44,6 +44,7 @@
44 }; 44 };
45 45
46 interrupts-extended0 { 46 interrupts-extended0 {
47 reg = <0x5000 0x100>;
47 interrupts-extended = <&test_intc0 1>, 48 interrupts-extended = <&test_intc0 1>,
48 <&test_intc1 2 3 4>, 49 <&test_intc1 2 3 4>,
49 <&test_intc2 5 6>, 50 <&test_intc2 5 6>,
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 7f51e266888b..964b596d343b 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -147,18 +147,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
147 147
148 pr_debug(" -> addrsize=%d\n", addrsize); 148 pr_debug(" -> addrsize=%d\n", addrsize);
149 149
150 /* If we were passed no "reg" property and we attempt to parse
151 * an interrupt-map, then #address-cells must be 0.
152 * Fail if it's not.
153 */
154 if (addr == NULL && addrsize != 0) {
155 pr_debug(" -> no reg passed in when needed !\n");
156 return -EINVAL;
157 }
158
159 /* Precalculate the match array - this simplifies match loop */ 150 /* Precalculate the match array - this simplifies match loop */
160 for (i = 0; i < addrsize; i++) 151 for (i = 0; i < addrsize; i++)
161 initial_match_array[i] = addr[i]; 152 initial_match_array[i] = addr ? addr[i] : 0;
162 for (i = 0; i < intsize; i++) 153 for (i = 0; i < intsize; i++)
163 initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); 154 initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
164 155
@@ -174,6 +165,15 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
174 return 0; 165 return 0;
175 } 166 }
176 167
168 /*
169 * interrupt-map parsing does not work without a reg
170 * property when #address-cells != 0
171 */
172 if (addrsize && !addr) {
173 pr_debug(" -> no reg passed in when needed !\n");
174 goto fail;
175 }
176
177 /* Now look for an interrupt-map */ 177 /* Now look for an interrupt-map */
178 imap = of_get_property(ipar, "interrupt-map", &imaplen); 178 imap = of_get_property(ipar, "interrupt-map", &imaplen);
179 /* No interrupt map, check for an interrupt parent */ 179 /* No interrupt map, check for an interrupt parent */