mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
			
			
This commit is contained in:
		
							parent
							
								
									15c9a0acc3
								
							
						
					
					
						commit
						53a42093d9
					
				
					 6 changed files with 189 additions and 0 deletions
				
			
		
							
								
								
									
										37
									
								
								arch/arm/boot/dts/testcases/tests-phandle.dtsi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								arch/arm/boot/dts/testcases/tests-phandle.dtsi
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
 | 
			
		||||
/ {
 | 
			
		||||
	testcase-data {
 | 
			
		||||
		phandle-tests {
 | 
			
		||||
			provider0: provider0 {
 | 
			
		||||
				#phandle-cells = <0>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			provider1: provider1 {
 | 
			
		||||
				#phandle-cells = <1>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			provider2: provider2 {
 | 
			
		||||
				#phandle-cells = <2>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			provider3: provider3 {
 | 
			
		||||
				#phandle-cells = <3>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			consumer-a {
 | 
			
		||||
				phandle-list =	<&provider1 1>,
 | 
			
		||||
						<&provider2 2 0>,
 | 
			
		||||
						<0>,
 | 
			
		||||
						<&provider3 4 4 3>,
 | 
			
		||||
						<&provider2 5 100>,
 | 
			
		||||
						<&provider0>,
 | 
			
		||||
						<&provider1 7>;
 | 
			
		||||
				phandle-list-names = "first", "second", "third";
 | 
			
		||||
 | 
			
		||||
				phandle-list-bad-phandle = <12345678 0 0>;
 | 
			
		||||
				phandle-list-bad-args = <&provider2 1 0>,
 | 
			
		||||
							<&provider3 0>;
 | 
			
		||||
			};
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										1
									
								
								arch/arm/boot/dts/testcases/tests.dtsi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								arch/arm/boot/dts/testcases/tests.dtsi
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
/include/ "tests-phandle.dtsi"
 | 
			
		||||
| 
						 | 
				
			
			@ -46,3 +46,5 @@ mmc@b000 {
 | 
			
		|||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/include/ "testcases/tests.dtsi"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,15 @@ config PROC_DEVICETREE
 | 
			
		|||
	  an image of the device tree that the kernel copies from Open
 | 
			
		||||
	  Firmware or other boot firmware. If unsure, say Y here.
 | 
			
		||||
 | 
			
		||||
config OF_SELFTEST
 | 
			
		||||
	bool "Device Tree Runtime self tests"
 | 
			
		||||
	help
 | 
			
		||||
	  This option builds in test cases for the device tree infrastructure
 | 
			
		||||
	  that are executed one at boot time, and the results dumped to the
 | 
			
		||||
	  console.
 | 
			
		||||
 | 
			
		||||
	  If unsure, say N here, but this option is safe to enable.
 | 
			
		||||
 | 
			
		||||
config OF_FLATTREE
 | 
			
		||||
	bool
 | 
			
		||||
	select DTC
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ obj-$(CONFIG_OF_GPIO)   += gpio.o
 | 
			
		|||
obj-$(CONFIG_OF_I2C)	+= of_i2c.o
 | 
			
		||||
obj-$(CONFIG_OF_NET)	+= of_net.o
 | 
			
		||||
obj-$(CONFIG_OF_SPI)	+= of_spi.o
 | 
			
		||||
obj-$(CONFIG_OF_SELFTEST) += selftest.o
 | 
			
		||||
obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 | 
			
		||||
obj-$(CONFIG_OF_PCI)	+= of_pci.o
 | 
			
		||||
obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										139
									
								
								drivers/of/selftest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								drivers/of/selftest.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Self tests for device tree subsystem
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define pr_fmt(fmt) "### %s(): " fmt, __func__
 | 
			
		||||
 | 
			
		||||
#include <linux/clk.h>
 | 
			
		||||
#include <linux/err.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/of.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
 | 
			
		||||
static bool selftest_passed = true;
 | 
			
		||||
#define selftest(result, fmt, ...) { \
 | 
			
		||||
	selftest_passed &= (result); \
 | 
			
		||||
	if (!(result)) \
 | 
			
		||||
		pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __init of_selftest_parse_phandle_with_args(void)
 | 
			
		||||
{
 | 
			
		||||
	struct device_node *np;
 | 
			
		||||
	struct of_phandle_args args;
 | 
			
		||||
	int rc, i;
 | 
			
		||||
	bool passed_all = true;
 | 
			
		||||
 | 
			
		||||
	pr_info("start\n");
 | 
			
		||||
	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
 | 
			
		||||
	if (!np) {
 | 
			
		||||
		pr_err("missing testcase data\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 7; i++) {
 | 
			
		||||
		bool passed = true;
 | 
			
		||||
		rc = of_parse_phandle_with_args(np, "phandle-list",
 | 
			
		||||
						"#phandle-cells", i, &args);
 | 
			
		||||
 | 
			
		||||
		/* Test the values from tests-phandle.dtsi */
 | 
			
		||||
		switch (i) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 1);
 | 
			
		||||
			passed &= (args.args[0] == (i + 1));
 | 
			
		||||
			break;
 | 
			
		||||
		case 1:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 2);
 | 
			
		||||
			passed &= (args.args[0] == (i + 1));
 | 
			
		||||
			passed &= (args.args[1] == 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 2:
 | 
			
		||||
			passed &= (rc == -ENOENT);
 | 
			
		||||
			break;
 | 
			
		||||
		case 3:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 3);
 | 
			
		||||
			passed &= (args.args[0] == (i + 1));
 | 
			
		||||
			passed &= (args.args[1] == 4);
 | 
			
		||||
			passed &= (args.args[2] == 3);
 | 
			
		||||
			break;
 | 
			
		||||
		case 4:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 2);
 | 
			
		||||
			passed &= (args.args[0] == (i + 1));
 | 
			
		||||
			passed &= (args.args[1] == 100);
 | 
			
		||||
			break;
 | 
			
		||||
		case 5:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 6:
 | 
			
		||||
			passed &= !rc;
 | 
			
		||||
			passed &= (args.args_count == 1);
 | 
			
		||||
			passed &= (args.args[0] == (i + 1));
 | 
			
		||||
			break;
 | 
			
		||||
		case 7:
 | 
			
		||||
			passed &= (rc == -EINVAL);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			passed = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!passed) {
 | 
			
		||||
			int j;
 | 
			
		||||
			pr_err("index %i - data error on node %s rc=%i regs=[",
 | 
			
		||||
				i, args.np->full_name, rc);
 | 
			
		||||
			for (j = 0; j < args.args_count; j++)
 | 
			
		||||
				printk(" %i", args.args[j]);
 | 
			
		||||
			printk(" ]\n");
 | 
			
		||||
 | 
			
		||||
			passed_all = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for missing list property */
 | 
			
		||||
	rc = of_parse_phandle_with_args(np, "phandle-list-missing",
 | 
			
		||||
					"#phandle-cells", 0, &args);
 | 
			
		||||
	passed_all &= (rc == -EINVAL);
 | 
			
		||||
 | 
			
		||||
	/* Check for missing cells property */
 | 
			
		||||
	rc = of_parse_phandle_with_args(np, "phandle-list",
 | 
			
		||||
					"#phandle-cells-missing", 0, &args);
 | 
			
		||||
	passed_all &= (rc == -EINVAL);
 | 
			
		||||
 | 
			
		||||
	/* Check for bad phandle in list */
 | 
			
		||||
	rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
 | 
			
		||||
					"#phandle-cells", 0, &args);
 | 
			
		||||
	passed_all &= (rc == -EINVAL);
 | 
			
		||||
 | 
			
		||||
	/* Check for incorrectly formed argument list */
 | 
			
		||||
	rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
 | 
			
		||||
					"#phandle-cells", 1, &args);
 | 
			
		||||
	passed_all &= (rc == -EINVAL);
 | 
			
		||||
 | 
			
		||||
	pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __init of_selftest(void)
 | 
			
		||||
{
 | 
			
		||||
	struct device_node *np;
 | 
			
		||||
 | 
			
		||||
	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
 | 
			
		||||
	if (!np) {
 | 
			
		||||
		pr_info("No testcase data in device tree; not running tests\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	of_node_put(np);
 | 
			
		||||
 | 
			
		||||
	pr_info("start of selftest - you will see error messages\n");
 | 
			
		||||
	of_selftest_parse_phandle_with_args();
 | 
			
		||||
	pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
late_initcall(of_selftest);
 | 
			
		||||
		Loading…
	
		Reference in a new issue