diff options
Diffstat (limited to 'drivers/of/unittest.c')
| -rw-r--r-- | drivers/of/unittest.c | 669 | 
1 files changed, 632 insertions, 37 deletions
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 68b87587b2ef..7e27670c3616 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -24,6 +24,7 @@  #include <linux/i2c.h>  #include <linux/i2c-mux.h> +#include <linux/gpio/driver.h>  #include <linux/bitops.h> @@ -46,6 +47,20 @@ static struct unittest_results {  	failed; \  }) +/* + * Expected message may have a message level other than KERN_INFO. + * Print the expected message only if the current loglevel will allow + * the actual message to print. + * + * Do not use EXPECT_BEGIN() or EXPECT_END() for messages generated by + * pr_debug(). + */ +#define EXPECT_BEGIN(level, fmt, ...) \ +	printk(level pr_fmt("EXPECT \\ : ") fmt, ##__VA_ARGS__) + +#define EXPECT_END(level, fmt, ...) \ +	printk(level pr_fmt("EXPECT / : ") fmt, ##__VA_ARGS__) +  static void __init of_unittest_find_node_by_name(void)  {  	struct device_node *np; @@ -444,29 +459,77 @@ static void __init of_unittest_parse_phandle_with_args(void)  	/* Check for missing cells property */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); +  	rc = of_parse_phandle_with_args(np, "phandle-list",  					"#phandle-cells-missing", 0, &args); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); +  	rc = of_count_phandle_with_args(np, "phandle-list",  					"#phandle-cells-missing"); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  	/* Check for bad phandle in list */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); +  	rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",  					"#phandle-cells", 0, &args); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); +  	rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle",  					"#phandle-cells"); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  	/* Check for incorrectly formed argument list */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); +  	rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",  					"#phandle-cells", 1, &args); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); +  	rc = of_count_phandle_with_args(np, "phandle-list-bad-args",  					"#phandle-cells"); + +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  } @@ -577,20 +640,41 @@ static void __init of_unittest_parse_phandle_with_args_map(void)  	/* Check for missing cells,map,mask property */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-b: could not get #phandle-missing-cells for /testcase-data/phandle-tests/provider1"); +  	rc = of_parse_phandle_with_args_map(np, "phandle-list",  					    "phandle-missing", 0, &args); +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-b: could not get #phandle-missing-cells for /testcase-data/phandle-tests/provider1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  	/* Check for bad phandle in list */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle"); +  	rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",  					    "phandle", 0, &args); +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  	/* Check for incorrectly formed argument list */  	memset(&args, 0, sizeof(args)); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: /testcase-data/phandle-tests/consumer-b: #phandle-cells = 2 found -1"); +  	rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args",  					    "phandle", 1, &args); +	EXPECT_END(KERN_INFO, +		   "OF: /testcase-data/phandle-tests/consumer-b: #phandle-cells = 2 found -1"); +  	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);  } @@ -1121,7 +1205,15 @@ static void __init of_unittest_platform_populate(void)  		np = of_find_node_by_path("/testcase-data/testcase-device2");  		pdev = of_find_device_by_node(np);  		unittest(pdev, "device 2 creation failed\n"); + +		EXPECT_BEGIN(KERN_INFO, +			     "platform testcase-data:testcase-device2: IRQ index 0 not found"); +  		irq = platform_get_irq(pdev, 0); + +		EXPECT_END(KERN_INFO, +			   "platform testcase-data:testcase-device2: IRQ index 0 not found"); +  		unittest(irq < 0 && irq != -EPROBE_DEFER,  			 "device parsing error failed - %d\n", irq);  	} @@ -1325,6 +1417,9 @@ static int __init unittest_data_add(void)  		return 0;  	} +	EXPECT_BEGIN(KERN_INFO, +		     "Duplicate name in testcase-data, renamed to \"duplicate-name#1\""); +  	/* attach the sub-tree to live tree */  	np = unittest_data_node->child;  	while (np) { @@ -1335,6 +1430,9 @@ static int __init unittest_data_add(void)  		np = next;  	} +	EXPECT_END(KERN_INFO, +		   "Duplicate name in testcase-data, renamed to \"duplicate-name#1\""); +  	of_overlay_mutex_unlock();  	return 0; @@ -1410,6 +1508,249 @@ static int of_path_platform_device_exists(const char *path)  	return pdev != NULL;  } +#ifdef CONFIG_OF_GPIO + +struct unittest_gpio_dev { +	struct gpio_chip chip; +}; + +static int unittest_gpio_chip_request_count; +static int unittest_gpio_probe_count; +static int unittest_gpio_probe_pass_count; + +static int unittest_gpio_chip_request(struct gpio_chip *chip, unsigned int offset) +{ +	unittest_gpio_chip_request_count++; + +	pr_debug("%s(): %s %d %d\n", __func__, chip->label, offset, +		 unittest_gpio_chip_request_count); +	return 0; +} + +static int unittest_gpio_probe(struct platform_device *pdev) +{ +	struct unittest_gpio_dev *devptr; +	int ret; + +	unittest_gpio_probe_count++; + +	devptr = kzalloc(sizeof(*devptr), GFP_KERNEL); +	if (!devptr) +		return -ENOMEM; + +	platform_set_drvdata(pdev, devptr); + +	devptr->chip.of_node = pdev->dev.of_node; +	devptr->chip.label = "of-unittest-gpio"; +	devptr->chip.base = -1; /* dynamic allocation */ +	devptr->chip.ngpio = 5; +	devptr->chip.request = unittest_gpio_chip_request; + +	ret = gpiochip_add_data(&devptr->chip, NULL); + +	unittest(!ret, +		 "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret); + +	if (!ret) +		unittest_gpio_probe_pass_count++; +	return ret; +} + +static int unittest_gpio_remove(struct platform_device *pdev) +{ +	struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev); +	struct device *dev = &pdev->dev; +	struct device_node *np = pdev->dev.of_node; + +	dev_dbg(dev, "%s for node @%pOF\n", __func__, np); + +	if (!gdev) +		return -EINVAL; + +	if (gdev->chip.base != -1) +		gpiochip_remove(&gdev->chip); + +	platform_set_drvdata(pdev, NULL); +	kfree(gdev); + +	return 0; +} + +static const struct of_device_id unittest_gpio_id[] = { +	{ .compatible = "unittest-gpio", }, +	{} +}; + +static struct platform_driver unittest_gpio_driver = { +	.probe	= unittest_gpio_probe, +	.remove	= unittest_gpio_remove, +	.driver	= { +		.name		= "unittest-gpio", +		.of_match_table	= of_match_ptr(unittest_gpio_id), +	}, +}; + +static void __init of_unittest_overlay_gpio(void) +{ +	int chip_request_count; +	int probe_pass_count; +	int ret; + +	/* +	 * tests: apply overlays before registering driver +	 * Similar to installing a driver as a module, the +	 * driver is registered after applying the overlays. +	 * +	 * The overlays are applied by overlay_data_apply() +	 * instead of of_unittest_apply_overlay() so that they +	 * will not be tracked.  Thus they will not be removed +	 * by of_unittest_destroy_tracked_overlays(). +	 * +	 * - apply overlay_gpio_01 +	 * - apply overlay_gpio_02a +	 * - apply overlay_gpio_02b +	 * - register driver +	 * +	 * register driver will result in +	 *   - probe and processing gpio hog for overlay_gpio_01 +	 *   - probe for overlay_gpio_02a +	 *   - processing gpio for overlay_gpio_02b +	 */ + +	probe_pass_count = unittest_gpio_probe_pass_count; +	chip_request_count = unittest_gpio_chip_request_count; + +	/* +	 * overlay_gpio_01 contains gpio node and child gpio hog node +	 * overlay_gpio_02a contains gpio node +	 * overlay_gpio_02b contains child gpio hog node +	 */ + +	unittest(overlay_data_apply("overlay_gpio_01", NULL), +		 "Adding overlay 'overlay_gpio_01' failed\n"); + +	unittest(overlay_data_apply("overlay_gpio_02a", NULL), +		 "Adding overlay 'overlay_gpio_02a' failed\n"); + +	unittest(overlay_data_apply("overlay_gpio_02b", NULL), +		 "Adding overlay 'overlay_gpio_02b' failed\n"); + +	/* +	 * messages are the result of the probes, after the +	 * driver is registered +	 */ + +	EXPECT_BEGIN(KERN_INFO, +		     "GPIO line <<int>> (line-B-input) hogged as input\n"); + +	EXPECT_BEGIN(KERN_INFO, +		     "GPIO line <<int>> (line-A-input) hogged as input\n"); + +	ret = platform_driver_register(&unittest_gpio_driver); +	if (unittest(ret == 0, "could not register unittest gpio driver\n")) +		return; + +	EXPECT_END(KERN_INFO, +		   "GPIO line <<int>> (line-A-input) hogged as input\n"); +	EXPECT_END(KERN_INFO, +		   "GPIO line <<int>> (line-B-input) hogged as input\n"); + +	unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, +		 "unittest_gpio_probe() failed or not called\n"); + +	unittest(chip_request_count + 2 == unittest_gpio_chip_request_count, +		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n", +		 unittest_gpio_chip_request_count - chip_request_count); + +	/* +	 * tests: apply overlays after registering driver +	 * +	 * Similar to a driver built-in to the kernel, the +	 * driver is registered before applying the overlays. +	 * +	 * overlay_gpio_03 contains gpio node and child gpio hog node +	 * +	 * - apply overlay_gpio_03 +	 * +	 * apply overlay will result in +	 *   - probe and processing gpio hog. +	 */ + +	probe_pass_count = unittest_gpio_probe_pass_count; +	chip_request_count = unittest_gpio_chip_request_count; + +	EXPECT_BEGIN(KERN_INFO, +		     "GPIO line <<int>> (line-D-input) hogged as input\n"); + +	/* overlay_gpio_03 contains gpio node and child gpio hog node */ + +	unittest(overlay_data_apply("overlay_gpio_03", NULL), +		 "Adding overlay 'overlay_gpio_03' failed\n"); + +	EXPECT_END(KERN_INFO, +		   "GPIO line <<int>> (line-D-input) hogged as input\n"); + +	unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, +		 "unittest_gpio_probe() failed or not called\n"); + +	unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, +		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n", +		 unittest_gpio_chip_request_count - chip_request_count); + +	/* +	 * overlay_gpio_04a contains gpio node +	 * +	 * - apply overlay_gpio_04a +	 * +	 * apply the overlay will result in +	 *   - probe for overlay_gpio_04a +	 */ + +	probe_pass_count = unittest_gpio_probe_pass_count; +	chip_request_count = unittest_gpio_chip_request_count; + +	/* overlay_gpio_04a contains gpio node */ + +	unittest(overlay_data_apply("overlay_gpio_04a", NULL), +		 "Adding overlay 'overlay_gpio_04a' failed\n"); + +	unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, +		 "unittest_gpio_probe() failed or not called\n"); + +	/* +	 * overlay_gpio_04b contains child gpio hog node +	 * +	 * - apply overlay_gpio_04b +	 * +	 * apply the overlay will result in +	 *   - processing gpio for overlay_gpio_04b +	 */ + +	EXPECT_BEGIN(KERN_INFO, +		     "GPIO line <<int>> (line-C-input) hogged as input\n"); + +	/* overlay_gpio_04b contains child gpio hog node */ + +	unittest(overlay_data_apply("overlay_gpio_04b", NULL), +		 "Adding overlay 'overlay_gpio_04b' failed\n"); + +	EXPECT_END(KERN_INFO, +		   "GPIO line <<int>> (line-C-input) hogged as input\n"); + +	unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, +		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n", +		 unittest_gpio_chip_request_count - chip_request_count); +} + +#else + +static void __init of_unittest_overlay_gpio(void) +{ +	/* skip tests */ +} + +#endif +  #if IS_BUILTIN(CONFIG_I2C)  /* get the i2c client device instantiated at the path */ @@ -1511,19 +1852,27 @@ static const char *overlay_name_from_nr(int nr)  static const char *bus_path = "/testcase-data/overlay-node/test-bus"; -/* it is guaranteed that overlay ids are assigned in sequence */ +/* FIXME: it is NOT guaranteed that overlay ids are assigned in sequence */ +  #define MAX_UNITTEST_OVERLAYS	256  static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_UNITTEST_OVERLAYS)];  static int overlay_first_id = -1; +static long of_unittest_overlay_tracked(int id) +{ +	if (WARN_ON(id >= MAX_UNITTEST_OVERLAYS)) +		return 0; +	return overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id); +} +  static void of_unittest_track_overlay(int id)  {  	if (overlay_first_id < 0)  		overlay_first_id = id;  	id -= overlay_first_id; -	/* we shouldn't need that many */ -	BUG_ON(id >= MAX_UNITTEST_OVERLAYS); +	if (WARN_ON(id >= MAX_UNITTEST_OVERLAYS)) +		return;  	overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);  } @@ -1532,7 +1881,8 @@ static void of_unittest_untrack_overlay(int id)  	if (overlay_first_id < 0)  		return;  	id -= overlay_first_id; -	BUG_ON(id >= MAX_UNITTEST_OVERLAYS); +	if (WARN_ON(id >= MAX_UNITTEST_OVERLAYS)) +		return;  	overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);  } @@ -1548,7 +1898,7 @@ static void of_unittest_destroy_tracked_overlays(void)  		defers = 0;  		/* remove in reverse order */  		for (id = MAX_UNITTEST_OVERLAYS - 1; id >= 0; id--) { -			if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id))) +			if (!of_unittest_overlay_tracked(id))  				continue;  			ovcs_id = id + overlay_first_id; @@ -1565,7 +1915,7 @@ static void of_unittest_destroy_tracked_overlays(void)  				continue;  			} -			overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id); +			of_unittest_untrack_overlay(id);  		}  	} while (defers > 0);  } @@ -1626,7 +1976,7 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,  		int unittest_nr, int before, int after,  		enum overlay_type ovtype)  { -	int ret, ovcs_id; +	int ret, ovcs_id, save_id;  	/* unittest device must be in before state */  	if (of_unittest_device_exists(unittest_nr, ovtype) != before) { @@ -1654,6 +2004,7 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,  		return -EINVAL;  	} +	save_id = ovcs_id;  	ret = of_overlay_remove(&ovcs_id);  	if (ret != 0) {  		unittest(0, "%s failed to be destroyed @\"%s\"\n", @@ -1661,6 +2012,7 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,  				unittest_path(unittest_nr, ovtype));  		return ret;  	} +	of_unittest_untrack_overlay(save_id);  	/* unittest device must be again in before state */  	if (of_unittest_device_exists(unittest_nr, PDEV_OVERLAY) != before) { @@ -1677,8 +2029,18 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,  /* test activation of device */  static void __init of_unittest_overlay_0(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest0/status"); +  	/* device should enable */ -	if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY)) +	ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest0/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 0); @@ -1687,28 +2049,58 @@ static void __init of_unittest_overlay_0(void)  /* test deactivation of device */  static void __init of_unittest_overlay_1(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest1/status"); +  	/* device should disable */ -	if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY)) +	ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest1/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 1); +  }  /* test activation of device */  static void __init of_unittest_overlay_2(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest2/status"); +  	/* device should enable */ -	if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY)) -		return; +	ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY); +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest2/status"); + +	if (ret) +		return;  	unittest(1, "overlay test %d passed\n", 2);  }  /* test deactivation of device */  static void __init of_unittest_overlay_3(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest3/status"); +  	/* device should disable */ -	if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY)) +	ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest3/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 3); @@ -1727,8 +2119,18 @@ static void __init of_unittest_overlay_4(void)  /* test overlay apply/revert sequence */  static void __init of_unittest_overlay_5(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest5/status"); +  	/* device should disable */ -	if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY)) +	ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest5/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 5); @@ -1742,6 +2144,8 @@ static void __init of_unittest_overlay_6(void)  	int before = 0, after = 1;  	const char *overlay_name; +	int ret; +  	/* unittest device must be in before state */  	for (i = 0; i < 2; i++) {  		if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY) @@ -1756,18 +2160,41 @@ static void __init of_unittest_overlay_6(void)  	}  	/* apply the overlays */ -	for (i = 0; i < 2; i++) { -		overlay_name = overlay_name_from_nr(overlay_nr + i); +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest6/status"); + +	overlay_name = overlay_name_from_nr(overlay_nr + 0); + +	ret = overlay_data_apply(overlay_name, &ovcs_id); -		if (!overlay_data_apply(overlay_name, &ovcs_id)) { -			unittest(0, "could not apply overlay \"%s\"\n", -					overlay_name); +	if (!ret) { +		unittest(0, "could not apply overlay \"%s\"\n", overlay_name); +			return; +	} +	ov_id[0] = ovcs_id; +	of_unittest_track_overlay(ov_id[0]); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest6/status"); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest7/status"); + +	overlay_name = overlay_name_from_nr(overlay_nr + 1); + +	ret = overlay_data_apply(overlay_name, &ovcs_id); + +	if (!ret) { +		unittest(0, "could not apply overlay \"%s\"\n", overlay_name);  			return; -		} -		ov_id[i] = ovcs_id; -		of_unittest_track_overlay(ov_id[i]);  	} +	ov_id[1] = ovcs_id; +	of_unittest_track_overlay(ov_id[1]); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest7/status"); +  	for (i = 0; i < 2; i++) {  		/* unittest device must be in after state */ @@ -1808,6 +2235,7 @@ static void __init of_unittest_overlay_6(void)  	}  	unittest(1, "overlay test %d passed\n", 6); +  }  /* test overlay application in sequence */ @@ -1816,26 +2244,65 @@ static void __init of_unittest_overlay_8(void)  	int i, ov_id[2], ovcs_id;  	int overlay_nr = 8, unittest_nr = 8;  	const char *overlay_name; +	int ret;  	/* we don't care about device state in this test */ +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/status"); + +	overlay_name = overlay_name_from_nr(overlay_nr + 0); + +	ret = overlay_data_apply(overlay_name, &ovcs_id); +	if (!ret) +		unittest(0, "could not apply overlay \"%s\"\n", overlay_name); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/status"); + +	if (!ret) +		return; + +	ov_id[0] = ovcs_id; +	of_unittest_track_overlay(ov_id[0]); + +	overlay_name = overlay_name_from_nr(overlay_nr + 1); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/property-foo"); +  	/* apply the overlays */ -	for (i = 0; i < 2; i++) { +	ret = overlay_data_apply(overlay_name, &ovcs_id); -		overlay_name = overlay_name_from_nr(overlay_nr + i); +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/property-foo"); -		if (!overlay_data_apply(overlay_name, &ovcs_id)) { -			unittest(0, "could not apply overlay \"%s\"\n", -					overlay_name); -			return; -		} -		ov_id[i] = ovcs_id; -		of_unittest_track_overlay(ov_id[i]); +	if (!ret) { +		unittest(0, "could not apply overlay \"%s\"\n", overlay_name); +		return;  	} +	ov_id[1] = ovcs_id; +	of_unittest_track_overlay(ov_id[1]); +  	/* now try to remove first overlay (it should fail) */  	ovcs_id = ov_id[0]; -	if (!of_overlay_remove(&ovcs_id)) { + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: node_overlaps_later_cs: #6 overlaps with #7 @/testcase-data/overlay-node/test-bus/test-unittest8"); + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: overlay #6 is not topmost"); + +	ret = of_overlay_remove(&ovcs_id); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: overlay #6 is not topmost"); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: node_overlaps_later_cs: #6 overlaps with #7 @/testcase-data/overlay-node/test-bus/test-unittest8"); + +	if (!ret) {  		unittest(0, "%s was destroyed @\"%s\"\n",  				overlay_name_from_nr(overlay_nr + 0),  				unittest_path(unittest_nr, @@ -1867,6 +2334,7 @@ static void __init of_unittest_overlay_10(void)  	/* device should disable */  	ret = of_unittest_apply_overlay_check(10, 10, 0, 1, PDEV_OVERLAY); +  	if (unittest(ret == 0,  			"overlay test %d failed; overlay application\n", 10))  		return; @@ -1890,6 +2358,7 @@ static void __init of_unittest_overlay_11(void)  	/* device should disable */  	ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,  			PDEV_OVERLAY); +  	unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11);  } @@ -2120,12 +2589,21 @@ static int of_unittest_overlay_i2c_init(void)  		return ret;  	ret = platform_driver_register(&unittest_i2c_bus_driver); +  	if (unittest(ret == 0,  			"could not register unittest i2c bus driver\n"))  		return ret;  #if IS_BUILTIN(CONFIG_I2C_MUX) + +	EXPECT_BEGIN(KERN_INFO, +		     "i2c i2c-1: Added multiplexed i2c bus 2"); +  	ret = i2c_add_driver(&unittest_i2c_mux_driver); + +	EXPECT_END(KERN_INFO, +		   "i2c i2c-1: Added multiplexed i2c bus 2"); +  	if (unittest(ret == 0,  			"could not register unittest i2c mux driver\n"))  		return ret; @@ -2145,8 +2623,18 @@ static void of_unittest_overlay_i2c_cleanup(void)  static void __init of_unittest_overlay_i2c_12(void)  { +	int ret; +  	/* device should enable */ -	if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY)) +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12/status"); + +	ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 12); @@ -2155,8 +2643,18 @@ static void __init of_unittest_overlay_i2c_12(void)  /* test deactivation of device */  static void __init of_unittest_overlay_i2c_13(void)  { +	int ret; + +	EXPECT_BEGIN(KERN_INFO, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13/status"); +  	/* device should disable */ -	if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY)) +	ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13/status"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 13); @@ -2169,8 +2667,18 @@ static void of_unittest_overlay_i2c_14(void)  static void __init of_unittest_overlay_i2c_15(void)  { +	int ret; +  	/* device should enable */ -	if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY)) +	EXPECT_BEGIN(KERN_INFO, +		     "i2c i2c-1: Added multiplexed i2c bus 3"); + +	ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY); + +	EXPECT_END(KERN_INFO, +		   "i2c i2c-1: Added multiplexed i2c bus 3"); + +	if (ret)  		return;  	unittest(1, "overlay test %d passed\n", 15); @@ -2242,6 +2750,8 @@ static void __init of_unittest_overlay(void)  	of_unittest_overlay_i2c_cleanup();  #endif +	of_unittest_overlay_gpio(); +  	of_unittest_destroy_tracked_overlays();  out: @@ -2295,6 +2805,12 @@ OVERLAY_INFO_EXTERN(overlay_11);  OVERLAY_INFO_EXTERN(overlay_12);  OVERLAY_INFO_EXTERN(overlay_13);  OVERLAY_INFO_EXTERN(overlay_15); +OVERLAY_INFO_EXTERN(overlay_gpio_01); +OVERLAY_INFO_EXTERN(overlay_gpio_02a); +OVERLAY_INFO_EXTERN(overlay_gpio_02b); +OVERLAY_INFO_EXTERN(overlay_gpio_03); +OVERLAY_INFO_EXTERN(overlay_gpio_04a); +OVERLAY_INFO_EXTERN(overlay_gpio_04b);  OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node);  OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop);  OVERLAY_INFO_EXTERN(overlay_bad_phandle); @@ -2319,6 +2835,12 @@ static struct overlay_info overlays[] = {  	OVERLAY_INFO(overlay_12, 0),  	OVERLAY_INFO(overlay_13, 0),  	OVERLAY_INFO(overlay_15, 0), +	OVERLAY_INFO(overlay_gpio_01, 0), +	OVERLAY_INFO(overlay_gpio_02a, 0), +	OVERLAY_INFO(overlay_gpio_02b, 0), +	OVERLAY_INFO(overlay_gpio_03, 0), +	OVERLAY_INFO(overlay_gpio_04a, 0), +	OVERLAY_INFO(overlay_gpio_04b, 0),  	OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL),  	OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL),  	OVERLAY_INFO(overlay_bad_phandle, -EINVAL), @@ -2470,6 +2992,7 @@ static __init void of_unittest_overlay_high_level(void)  	struct device_node *overlay_base_symbols;  	struct device_node **pprev;  	struct property *prop; +	int ret;  	if (!overlay_base_root) {  		unittest(0, "overlay_base_root not initialized\n"); @@ -2584,15 +3107,86 @@ static __init void of_unittest_overlay_high_level(void)  	/* now do the normal overlay usage test */ -	unittest(overlay_data_apply("overlay", NULL), -		 "Adding overlay 'overlay' failed\n"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/status"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/status"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@30/incline-up"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@40/incline-up"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/status"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/color"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/rate"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/hvac_2"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_left"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_right"); + +	ret = overlay_data_apply("overlay", NULL); + +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_right"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_left"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/hvac_2"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/rate"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/color"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/status"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@40/incline-up"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@30/incline-up"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/status"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/status"); + +	unittest(ret, "Adding overlay 'overlay' failed\n"); + +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/controller/name");  	unittest(overlay_data_apply("overlay_bad_add_dup_node", NULL),  		 "Adding overlay 'overlay_bad_add_dup_node' failed\n"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/controller/name"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller"); + +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); +	EXPECT_BEGIN(KERN_ERR, +		     "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail"); +  	unittest(overlay_data_apply("overlay_bad_add_dup_prop", NULL),  		 "Adding overlay 'overlay_bad_add_dup_prop' failed\n"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); +	EXPECT_END(KERN_ERR, +		   "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); +  	unittest(overlay_data_apply("overlay_bad_phandle", NULL),  		 "Adding overlay 'overlay_bad_phandle' failed\n"); @@ -2616,6 +3210,8 @@ static int __init of_unittest(void)  	struct device_node *np;  	int res; +	pr_info("start of unittest - you will see error messages\n"); +  	/* adding data for unittest */  	if (IS_ENABLED(CONFIG_UML)) @@ -2634,7 +3230,6 @@ static int __init of_unittest(void)  	}  	of_node_put(np); -	pr_info("start of unittest - you will see error messages\n");  	of_unittest_check_tree_linkage();  	of_unittest_check_phandles();  	of_unittest_find_node_by_name();  |