Commit a9f10ca76d784023fc45f01f025b54e9960f4ec1
1 parent
624cfca534
Exists in
master
and in
16 other branches
of: Add testcases for interrupt parsing
This patch extends the DT selftest code with some test cases for the interrupt parsing functions. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Showing 3 changed files with 127 additions and 6 deletions Side-by-side Diff
arch/arm/boot/dts/testcases/tests-interrupts.dtsi
1 | + | |
2 | +/ { | |
3 | + testcase-data { | |
4 | + interrupts { | |
5 | + #address-cells = <0>; | |
6 | + test_intc0: intc0 { | |
7 | + interrupt-controller; | |
8 | + #interrupt-cells = <1>; | |
9 | + }; | |
10 | + | |
11 | + test_intc1: intc1 { | |
12 | + interrupt-controller; | |
13 | + #interrupt-cells = <3>; | |
14 | + }; | |
15 | + | |
16 | + test_intc2: intc2 { | |
17 | + interrupt-controller; | |
18 | + #interrupt-cells = <2>; | |
19 | + }; | |
20 | + | |
21 | + test_intmap0: intmap0 { | |
22 | + #interrupt-cells = <1>; | |
23 | + #address-cells = <0>; | |
24 | + interrupt-map = <1 &test_intc0 9>, | |
25 | + <2 &test_intc1 10 11 12>, | |
26 | + <3 &test_intc2 13 14>, | |
27 | + <4 &test_intc2 15 16>; | |
28 | + }; | |
29 | + | |
30 | + interrupts0 { | |
31 | + interrupt-parent = <&test_intc0>; | |
32 | + interrupts = <1>, <2>, <3>, <4>; | |
33 | + }; | |
34 | + | |
35 | + interrupts1 { | |
36 | + interrupt-parent = <&test_intmap0>; | |
37 | + interrupts = <1>, <2>, <3>, <4>; | |
38 | + }; | |
39 | + }; | |
40 | + }; | |
41 | +}; |
arch/arm/boot/dts/testcases/tests.dtsi
drivers/of/selftest.c
... | ... | @@ -9,18 +9,24 @@ |
9 | 9 | #include <linux/errno.h> |
10 | 10 | #include <linux/module.h> |
11 | 11 | #include <linux/of.h> |
12 | +#include <linux/of_irq.h> | |
12 | 13 | #include <linux/list.h> |
13 | 14 | #include <linux/mutex.h> |
14 | 15 | #include <linux/slab.h> |
15 | 16 | #include <linux/device.h> |
16 | 17 | |
17 | -static bool selftest_passed = true; | |
18 | +static struct selftest_results { | |
19 | + int passed; | |
20 | + int failed; | |
21 | +} selftest_results; | |
22 | + | |
18 | 23 | #define selftest(result, fmt, ...) { \ |
19 | 24 | if (!(result)) { \ |
20 | - pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ | |
21 | - selftest_passed = false; \ | |
25 | + selftest_results.failed++; \ | |
26 | + pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \ | |
22 | 27 | } else { \ |
23 | - pr_info("pass %s:%i\n", __FILE__, __LINE__); \ | |
28 | + selftest_results.passed++; \ | |
29 | + pr_debug("pass %s():%i\n", __func__, __LINE__); \ | |
24 | 30 | } \ |
25 | 31 | } |
26 | 32 | |
... | ... | @@ -131,7 +137,6 @@ |
131 | 137 | struct device_node *np; |
132 | 138 | int rc; |
133 | 139 | |
134 | - pr_info("start\n"); | |
135 | 140 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); |
136 | 141 | if (!np) { |
137 | 142 | pr_err("No testcase data in device tree\n"); |
... | ... | @@ -154,6 +159,78 @@ |
154 | 159 | selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); |
155 | 160 | } |
156 | 161 | |
162 | +static void __init of_selftest_parse_interrupts(void) | |
163 | +{ | |
164 | + struct device_node *np; | |
165 | + struct of_phandle_args args; | |
166 | + int i, rc; | |
167 | + | |
168 | + np = of_find_node_by_path("/testcase-data/interrupts/interrupts0"); | |
169 | + if (!np) { | |
170 | + pr_err("missing testcase data\n"); | |
171 | + return; | |
172 | + } | |
173 | + | |
174 | + for (i = 0; i < 4; i++) { | |
175 | + bool passed = true; | |
176 | + args.args_count = 0; | |
177 | + rc = of_irq_parse_one(np, i, &args); | |
178 | + | |
179 | + passed &= !rc; | |
180 | + passed &= (args.args_count == 1); | |
181 | + passed &= (args.args[0] == (i + 1)); | |
182 | + | |
183 | + selftest(passed, "index %i - data error on node %s rc=%i\n", | |
184 | + i, args.np->full_name, rc); | |
185 | + } | |
186 | + of_node_put(np); | |
187 | + | |
188 | + np = of_find_node_by_path("/testcase-data/interrupts/interrupts1"); | |
189 | + if (!np) { | |
190 | + pr_err("missing testcase data\n"); | |
191 | + return; | |
192 | + } | |
193 | + | |
194 | + for (i = 0; i < 4; i++) { | |
195 | + bool passed = true; | |
196 | + args.args_count = 0; | |
197 | + rc = of_irq_parse_one(np, i, &args); | |
198 | + | |
199 | + /* Test the values from tests-phandle.dtsi */ | |
200 | + switch (i) { | |
201 | + case 0: | |
202 | + passed &= !rc; | |
203 | + passed &= (args.args_count == 1); | |
204 | + passed &= (args.args[0] == 9); | |
205 | + break; | |
206 | + case 1: | |
207 | + passed &= !rc; | |
208 | + passed &= (args.args_count == 3); | |
209 | + passed &= (args.args[0] == 10); | |
210 | + passed &= (args.args[1] == 11); | |
211 | + passed &= (args.args[2] == 12); | |
212 | + break; | |
213 | + case 2: | |
214 | + passed &= !rc; | |
215 | + passed &= (args.args_count == 2); | |
216 | + passed &= (args.args[0] == 13); | |
217 | + passed &= (args.args[1] == 14); | |
218 | + break; | |
219 | + case 3: | |
220 | + passed &= !rc; | |
221 | + passed &= (args.args_count == 2); | |
222 | + passed &= (args.args[0] == 15); | |
223 | + passed &= (args.args[1] == 16); | |
224 | + break; | |
225 | + default: | |
226 | + passed = false; | |
227 | + } | |
228 | + selftest(passed, "index %i - data error on node %s rc=%i\n", | |
229 | + i, args.np->full_name, rc); | |
230 | + } | |
231 | + of_node_put(np); | |
232 | +} | |
233 | + | |
157 | 234 | static int __init of_selftest(void) |
158 | 235 | { |
159 | 236 | struct device_node *np; |
... | ... | @@ -168,7 +245,9 @@ |
168 | 245 | pr_info("start of selftest - you will see error messages\n"); |
169 | 246 | of_selftest_parse_phandle_with_args(); |
170 | 247 | of_selftest_property_match_string(); |
171 | - pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL"); | |
248 | + of_selftest_parse_interrupts(); | |
249 | + pr_info("end of selftest - %i passed, %i failed\n", | |
250 | + selftest_results.passed, selftest_results.failed); | |
172 | 251 | return 0; |
173 | 252 | } |
174 | 253 | late_initcall(of_selftest); |