diff options
author | Grant Likely <grant.likely@linaro.org> | 2013-11-01 13:50:50 -0400 |
---|---|---|
committer | Shawn Guo <shawn.guo@freescale.com> | 2014-05-16 04:19:13 -0400 |
commit | 9c67477d3750f413e59e04c91abfbcd6076930a9 (patch) | |
tree | 8eade8e732bb6efcf141d4062dcbcb8485cc6ef2 | |
parent | bb976a3070d8f947dddbf738cfe36487ec17ab2a (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.dtsi | 7 | ||||
-rw-r--r-- | drivers/of/irq.c | 20 |
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 */ |