Commit 53a42093d96ef5ede3b4f4cdb8f3256f27228ab0

Authored by Grant Likely
1 parent 15c9a0acc3

of: Add device tree selftests

Add some runtime test cases for the library of device tree parsing functions.

v2: - Add testcase for phandle with 0 args
    - Don't run testcases if testcase data isn't present in device tree

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

Showing 6 changed files with 189 additions and 0 deletions Side-by-side Diff

arch/arm/boot/dts/testcases/tests-phandle.dtsi
  1 +
  2 +/ {
  3 + testcase-data {
  4 + phandle-tests {
  5 + provider0: provider0 {
  6 + #phandle-cells = <0>;
  7 + };
  8 +
  9 + provider1: provider1 {
  10 + #phandle-cells = <1>;
  11 + };
  12 +
  13 + provider2: provider2 {
  14 + #phandle-cells = <2>;
  15 + };
  16 +
  17 + provider3: provider3 {
  18 + #phandle-cells = <3>;
  19 + };
  20 +
  21 + consumer-a {
  22 + phandle-list = <&provider1 1>,
  23 + <&provider2 2 0>,
  24 + <0>,
  25 + <&provider3 4 4 3>,
  26 + <&provider2 5 100>,
  27 + <&provider0>,
  28 + <&provider1 7>;
  29 + phandle-list-names = "first", "second", "third";
  30 +
  31 + phandle-list-bad-phandle = <12345678 0 0>;
  32 + phandle-list-bad-args = <&provider2 1 0>,
  33 + <&provider3 0>;
  34 + };
  35 + };
  36 + };
  37 +};
arch/arm/boot/dts/testcases/tests.dtsi
  1 +/include/ "tests-phandle.dtsi"
arch/arm/boot/dts/versatile-pb.dts
... ... @@ -46,4 +46,6 @@
46 46 };
47 47 };
48 48 };
  49 +
  50 +/include/ "testcases/tests.dtsi"
... ... @@ -15,6 +15,15 @@
15 15 an image of the device tree that the kernel copies from Open
16 16 Firmware or other boot firmware. If unsure, say Y here.
17 17  
  18 +config OF_SELFTEST
  19 + bool "Device Tree Runtime self tests"
  20 + help
  21 + This option builds in test cases for the device tree infrastructure
  22 + that are executed one at boot time, and the results dumped to the
  23 + console.
  24 +
  25 + If unsure, say N here, but this option is safe to enable.
  26 +
18 27 config OF_FLATTREE
19 28 bool
20 29 select DTC
... ... @@ -8,6 +8,7 @@
8 8 obj-$(CONFIG_OF_I2C) += of_i2c.o
9 9 obj-$(CONFIG_OF_NET) += of_net.o
10 10 obj-$(CONFIG_OF_SPI) += of_spi.o
  11 +obj-$(CONFIG_OF_SELFTEST) += selftest.o
11 12 obj-$(CONFIG_OF_MDIO) += of_mdio.o
12 13 obj-$(CONFIG_OF_PCI) += of_pci.o
13 14 obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
drivers/of/selftest.c
  1 +/*
  2 + * Self tests for device tree subsystem
  3 + */
  4 +
  5 +#define pr_fmt(fmt) "### %s(): " fmt, __func__
  6 +
  7 +#include <linux/clk.h>
  8 +#include <linux/err.h>
  9 +#include <linux/errno.h>
  10 +#include <linux/module.h>
  11 +#include <linux/of.h>
  12 +#include <linux/list.h>
  13 +#include <linux/mutex.h>
  14 +#include <linux/slab.h>
  15 +#include <linux/device.h>
  16 +
  17 +static bool selftest_passed = true;
  18 +#define selftest(result, fmt, ...) { \
  19 + selftest_passed &= (result); \
  20 + if (!(result)) \
  21 + pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
  22 +}
  23 +
  24 +static void __init of_selftest_parse_phandle_with_args(void)
  25 +{
  26 + struct device_node *np;
  27 + struct of_phandle_args args;
  28 + int rc, i;
  29 + bool passed_all = true;
  30 +
  31 + pr_info("start\n");
  32 + np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
  33 + if (!np) {
  34 + pr_err("missing testcase data\n");
  35 + return;
  36 + }
  37 +
  38 + for (i = 0; i < 7; i++) {
  39 + bool passed = true;
  40 + rc = of_parse_phandle_with_args(np, "phandle-list",
  41 + "#phandle-cells", i, &args);
  42 +
  43 + /* Test the values from tests-phandle.dtsi */
  44 + switch (i) {
  45 + case 0:
  46 + passed &= !rc;
  47 + passed &= (args.args_count == 1);
  48 + passed &= (args.args[0] == (i + 1));
  49 + break;
  50 + case 1:
  51 + passed &= !rc;
  52 + passed &= (args.args_count == 2);
  53 + passed &= (args.args[0] == (i + 1));
  54 + passed &= (args.args[1] == 0);
  55 + break;
  56 + case 2:
  57 + passed &= (rc == -ENOENT);
  58 + break;
  59 + case 3:
  60 + passed &= !rc;
  61 + passed &= (args.args_count == 3);
  62 + passed &= (args.args[0] == (i + 1));
  63 + passed &= (args.args[1] == 4);
  64 + passed &= (args.args[2] == 3);
  65 + break;
  66 + case 4:
  67 + passed &= !rc;
  68 + passed &= (args.args_count == 2);
  69 + passed &= (args.args[0] == (i + 1));
  70 + passed &= (args.args[1] == 100);
  71 + break;
  72 + case 5:
  73 + passed &= !rc;
  74 + passed &= (args.args_count == 0);
  75 + break;
  76 + case 6:
  77 + passed &= !rc;
  78 + passed &= (args.args_count == 1);
  79 + passed &= (args.args[0] == (i + 1));
  80 + break;
  81 + case 7:
  82 + passed &= (rc == -EINVAL);
  83 + break;
  84 + default:
  85 + passed = false;
  86 + }
  87 +
  88 + if (!passed) {
  89 + int j;
  90 + pr_err("index %i - data error on node %s rc=%i regs=[",
  91 + i, args.np->full_name, rc);
  92 + for (j = 0; j < args.args_count; j++)
  93 + printk(" %i", args.args[j]);
  94 + printk(" ]\n");
  95 +
  96 + passed_all = false;
  97 + }
  98 + }
  99 +
  100 + /* Check for missing list property */
  101 + rc = of_parse_phandle_with_args(np, "phandle-list-missing",
  102 + "#phandle-cells", 0, &args);
  103 + passed_all &= (rc == -EINVAL);
  104 +
  105 + /* Check for missing cells property */
  106 + rc = of_parse_phandle_with_args(np, "phandle-list",
  107 + "#phandle-cells-missing", 0, &args);
  108 + passed_all &= (rc == -EINVAL);
  109 +
  110 + /* Check for bad phandle in list */
  111 + rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
  112 + "#phandle-cells", 0, &args);
  113 + passed_all &= (rc == -EINVAL);
  114 +
  115 + /* Check for incorrectly formed argument list */
  116 + rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
  117 + "#phandle-cells", 1, &args);
  118 + passed_all &= (rc == -EINVAL);
  119 +
  120 + pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
  121 +}
  122 +
  123 +static int __init of_selftest(void)
  124 +{
  125 + struct device_node *np;
  126 +
  127 + np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
  128 + if (!np) {
  129 + pr_info("No testcase data in device tree; not running tests\n");
  130 + return 0;
  131 + }
  132 + of_node_put(np);
  133 +
  134 + pr_info("start of selftest - you will see error messages\n");
  135 + of_selftest_parse_phandle_with_args();
  136 + pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
  137 + return 0;
  138 +}
  139 +late_initcall(of_selftest);