diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-06 05:33:07 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-06 05:33:07 +0300 |
commit | 3ef2bc099d1cce09e2844467e2ced98e1a44609d (patch) | |
tree | be3d1ea5da1ba9f3a664d5da7f34574bb7930ce7 /drivers/of | |
parent | 2eecf3a49f1ff24c6116c954dd74e83f227fc716 (diff) | |
parent | 17a70355ea576843a7ac851f1db26872a50b2850 (diff) | |
download | linux-3ef2bc099d1cce09e2844467e2ced98e1a44609d.tar.xz |
Merge tag 'devicetree-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull DeviceTree updates from Rob Herring:
- fix sparse warnings in drivers/of/
- add more overlay unittests
- update dtc to v1.4.4-8-g756ffc4f52f6. This adds more checks on dts
files such as unit-address formatting and stricter character sets for
node and property names
- add a common DT modalias function
- move trivial-devices.txt up and out of i2c dir
- ARM NVIC interrupt controller binding
- vendor prefixes for Sensirion, Dioo, Nordic, ROHM
- correct some binding file locations
* tag 'devicetree-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (24 commits)
of: fix sparse warnings in fdt, irq, reserved mem, and resolver code
of: fix sparse warning in of_pci_range_parser_one
of: fix sparse warnings in of_find_next_cache_node
of/unittest: Missing unlocks on error
of: fix uninitialized variable warning for overlay test
of: fix unittest build without CONFIG_OF_OVERLAY
of: Add unit tests for applying overlays
of: per-file dtc compiler flags
fpga: region: add missing DT documentation for config complete timeout
of: Add vendor prefix for ROHM Semiconductor
of: fix "/cpus" reference leak in of_numa_parse_cpu_nodes()
of: Add vendor prefix for Nordic Semiconductor
dt-bindings: arm,nvic: Binding for ARM NVIC interrupt controller on Cortex-M
dtc: update warning settings for new bus and node/property name checks
scripts/dtc: Update to upstream version v1.4.4-8-g756ffc4f52f6
scripts/dtc: automate getting dtc version and log in update script
of: Add function for generating a DT modalias with a newline
of: fix of_device_get_modalias returned length when truncating buffers
Documentation: devicetree: move trivial-devices out of I2C realm
dt-bindings: add vendor prefix for Dioo
..
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 2 | ||||
-rw-r--r-- | drivers/of/base.c | 13 | ||||
-rw-r--r-- | drivers/of/device.c | 20 | ||||
-rw-r--r-- | drivers/of/fdt.c | 18 | ||||
-rw-r--r-- | drivers/of/irq.c | 2 | ||||
-rw-r--r-- | drivers/of/of_numa.c | 2 | ||||
-rw-r--r-- | drivers/of/of_private.h | 12 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 2 | ||||
-rw-r--r-- | drivers/of/resolver.c | 2 | ||||
-rw-r--r-- | drivers/of/unittest-data/Makefile | 17 | ||||
-rw-r--r-- | drivers/of/unittest-data/overlay.dts | 53 | ||||
-rw-r--r-- | drivers/of/unittest-data/overlay_bad_phandle.dts | 20 | ||||
-rw-r--r-- | drivers/of/unittest-data/overlay_base.dts | 80 | ||||
-rw-r--r-- | drivers/of/unittest.c | 321 |
14 files changed, 540 insertions, 24 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 02b2903fe9d2..72914cdfce2a 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -263,7 +263,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, if (!parser->range || parser->range + parser->np > parser->end) return NULL; - range->pci_space = parser->range[0]; + range->pci_space = be32_to_cpup(parser->range); range->flags = of_bus_pci_get_flags(parser->range); range->pci_addr = of_read_number(parser->range + 1, ns); range->cpu_addr = of_translate_address(parser->node, diff --git a/drivers/of/base.c b/drivers/of/base.c index 0ea16bd3c8f1..28d5f53bc631 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2281,15 +2281,14 @@ EXPORT_SYMBOL_GPL(of_console_check); */ struct device_node *of_find_next_cache_node(const struct device_node *np) { - struct device_node *child; - const phandle *handle; + struct device_node *child, *cache_node; - handle = of_get_property(np, "l2-cache", NULL); - if (!handle) - handle = of_get_property(np, "next-level-cache", NULL); + cache_node = of_parse_phandle(np, "l2-cache", 0); + if (!cache_node) + cache_node = of_parse_phandle(np, "next-level-cache", 0); - if (handle) - return of_find_node_by_phandle(be32_to_cpup(handle)); + if (cache_node) + return cache_node; /* OF on pmac has nodes instead of properties named "l2-cache" * beneath CPU nodes. diff --git a/drivers/of/device.c b/drivers/of/device.c index b1e6bebda3f3..6e2f9113b1b7 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -176,7 +176,7 @@ const void *of_device_get_match_data(const struct device *dev) } EXPORT_SYMBOL(of_device_get_match_data); -ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) +static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) { const char *compat; int cplen, i; @@ -223,9 +223,8 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) str[i] = '_'; } - return tsize; + return repend; } -EXPORT_SYMBOL_GPL(of_device_get_modalias); int of_device_request_module(struct device *dev) { @@ -251,6 +250,21 @@ int of_device_request_module(struct device *dev) EXPORT_SYMBOL_GPL(of_device_request_module); /** + * of_device_modalias - Fill buffer with newline terminated modalias string + */ +ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) +{ + ssize_t sl = of_device_get_modalias(dev, str, len - 2); + if (sl < 0) + return sl; + + str[sl++] = '\n'; + str[sl] = 0; + return sl; +} +EXPORT_SYMBOL_GPL(of_device_modalias); + +/** * of_device_uevent - Display OF related uevent information */ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index e5ce4b59e162..a0972219ccfc 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -31,6 +31,8 @@ #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ #include <asm/page.h> +#include "of_private.h" + /* * of_fdt_limit_memory - limit the number of regions in the /memory node * @limit: maximum entries @@ -46,8 +48,8 @@ void of_fdt_limit_memory(int limit) const void *val; int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT; int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; - const uint32_t *addr_prop; - const uint32_t *size_prop; + const __be32 *addr_prop; + const __be32 *size_prop; int root_offset; int cell_size; @@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob, * Returns NULL on failure or the memory chunk containing the unflattened * device tree on success. */ -static void *__unflatten_device_tree(const void *blob, - struct device_node *dad, - struct device_node **mynodes, - void *(*dt_alloc)(u64 size, u64 align), - bool detached) +void *__unflatten_device_tree(const void *blob, + struct device_node *dad, + struct device_node **mynodes, + void *(*dt_alloc)(u64 size, u64 align), + bool detached) { int size; void *mem; @@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void) /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ of_alias_scan(early_init_dt_alloc_memory_arch); + + unittest_unflatten_overlay_base(); } /** diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 7c56b72d1dc6..d11437cb1187 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -102,7 +102,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; __be32 initial_match_array[MAX_PHANDLE_ARGS]; const __be32 *match_array = initial_match_array; - const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; + const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) }; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i, rc = -EINVAL; diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c index a53982a330ea..2db1f7a04baf 100644 --- a/drivers/of/of_numa.c +++ b/drivers/of/of_numa.c @@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void) else node_set(nid, numa_nodes_parsed); } + + of_node_put(cpus); } static int __init of_numa_parse_memory_nodes(void) diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 18bbb4517e25..4ebb0149d118 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -55,6 +55,18 @@ static inline int of_property_notify(int action, struct device_node *np, } #endif /* CONFIG_OF_DYNAMIC */ +#if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY) +extern void __init unittest_unflatten_overlay_base(void); +#else +static inline void unittest_unflatten_overlay_base(void) {}; +#endif + +extern void *__unflatten_device_tree(const void *blob, + struct device_node *dad, + struct device_node **mynodes, + void *(*dt_alloc)(u64 size, u64 align), + bool detached); + /** * General utilities for working with live trees. * diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index d507c3569a88..4dec07ea510f 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) const struct of_device_id *i; for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { - reservedmem_of_init_fn initfn = i->data; + int const (*initfn)(struct reserved_mem *rmem) = i->data; const char *compat = i->compatible; if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 7ae9863cb0a4..771f4844c781 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -92,7 +92,7 @@ static void adjust_overlay_phandles(struct device_node *overlay, if (phandle == OF_PHANDLE_ILLEGAL) continue; - *(uint32_t *)prop->value = cpu_to_be32(overlay->phandle); + *(__be32 *)prop->value = cpu_to_be32(overlay->phandle); } for_each_child_of_node(overlay, child) diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile index 1ac5cc01d627..6e00a9c69e58 100644 --- a/drivers/of/unittest-data/Makefile +++ b/drivers/of/unittest-data/Makefile @@ -1,7 +1,18 @@ obj-y += testcases.dtb.o +obj-y += overlay.dtb.o +obj-y += overlay_bad_phandle.dtb.o +obj-y += overlay_base.dtb.o targets += testcases.dtb testcases.dtb.S +targets += overlay.dtb overlay.dtb.S +targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S +targets += overlay_base.dtb overlay_base.dtb.S -.SECONDARY: \ - $(obj)/testcases.dtb.S \ - $(obj)/testcases.dtb +.PRECIOUS: \ + $(obj)/%.dtb.S \ + $(obj)/%.dtb + +# enable creation of __symbols__ node +DTC_FLAGS_overlay := -@ +DTC_FLAGS_overlay_bad_phandle := -@ +DTC_FLAGS_overlay_base := -@ diff --git a/drivers/of/unittest-data/overlay.dts b/drivers/of/unittest-data/overlay.dts new file mode 100644 index 000000000000..6cd7e6a0c13e --- /dev/null +++ b/drivers/of/unittest-data/overlay.dts @@ -0,0 +1,53 @@ +/dts-v1/; +/plugin/; + +/ { + + fragment@0 { + target = <&electric_1>; + + __overlay__ { + status = "ok"; + + hvac_2: hvac-large-1 { + compatible = "ot,hvac-large"; + heat-range = < 40 75 >; + cool-range = < 65 80 >; + }; + }; + }; + + fragment@1 { + target = <&rides_1>; + + __overlay__ { + #address-cells = <1>; + #size-cells = <1>; + status = "ok"; + + ride@200 { + compatible = "ot,ferris-wheel"; + reg = < 0x00000200 0x100 >; + hvac-provider = < &hvac_2 >; + hvac-thermostat = < 27 32 > ; + hvac-zones = < 12 5 >; + hvac-zone-names = "operator", "snack-bar"; + spin-controller = < &spin_ctrl_1 3 >; + spin-rph = < 30 >; + gondolas = < 16 >; + gondola-capacity = < 6 >; + }; + }; + }; + + fragment@2 { + target = <&lights_2>; + + __overlay__ { + status = "ok"; + color = "purple", "white", "red", "green"; + rate = < 3 256 >; + }; + }; + +}; diff --git a/drivers/of/unittest-data/overlay_bad_phandle.dts b/drivers/of/unittest-data/overlay_bad_phandle.dts new file mode 100644 index 000000000000..270ee885a623 --- /dev/null +++ b/drivers/of/unittest-data/overlay_bad_phandle.dts @@ -0,0 +1,20 @@ +/dts-v1/; +/plugin/; + +/ { + + fragment@0 { + target = <&electric_1>; + + __overlay__ { + + // This label should cause an error when the overlay + // is applied. There is already a phandle value + // in the base tree for motor-1. + spin_ctrl_1_conflict: motor-1 { + accelerate = < 3 >; + decelerate = < 5 >; + }; + }; + }; +}; diff --git a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts new file mode 100644 index 000000000000..5566b27fb61a --- /dev/null +++ b/drivers/of/unittest-data/overlay_base.dts @@ -0,0 +1,80 @@ +/dts-v1/; +/plugin/; + +/* + * Base device tree that overlays will be applied against. + * + * Do not add any properties in node "/". + * Do not add any nodes other than "/testcase-data-2" in node "/". + * Do not add anything that would result in dtc creating node "/__fixups__". + * dtc will create nodes "/__symbols__" and "/__local_fixups__". + */ + +/ { + testcase-data-2 { + #address-cells = <1>; + #size-cells = <1>; + + electric_1: substation@100 { + compatible = "ot,big-volts-control"; + reg = < 0x00000100 0x100 >; + status = "disabled"; + + hvac_1: hvac-medium-1 { + compatible = "ot,hvac-medium"; + heat-range = < 50 75 >; + cool-range = < 60 80 >; + }; + + spin_ctrl_1: motor-1 { + compatible = "ot,ferris-wheel-motor"; + spin = "clockwise"; + }; + + spin_ctrl_2: motor-8 { + compatible = "ot,roller-coaster-motor"; + }; + }; + + rides_1: fairway-1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ot,rides"; + status = "disabled"; + orientation = < 127 >; + + ride@100 { + compatible = "ot,roller-coaster"; + reg = < 0x00000100 0x100 >; + hvac-provider = < &hvac_1 >; + hvac-thermostat = < 29 > ; + hvac-zones = < 14 >; + hvac-zone-names = "operator"; + spin-controller = < &spin_ctrl_2 5 &spin_ctrl_2 7 >; + spin-controller-names = "track_1", "track_2"; + queues = < 2 >; + }; + }; + + lights_1: lights@30000 { + compatible = "ot,work-lights"; + reg = < 0x00030000 0x1000 >; + status = "disabled"; + }; + + lights_2: lights@40000 { + compatible = "ot,show-lights"; + reg = < 0x00040000 0x1000 >; + status = "disabled"; + rate = < 13 138 >; + }; + + retail_1: vending@50000 { + reg = < 0x00050000 0x1000 >; + compatible = "ot,tickets"; + status = "disabled"; + }; + + }; +}; + diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 62db55b97c10..987a1530282a 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -8,6 +8,7 @@ #include <linux/err.h> #include <linux/errno.h> #include <linux/hashtable.h> +#include <linux/libfdt.h> #include <linux/of.h> #include <linux/of_fdt.h> #include <linux/of_irq.h> @@ -1925,6 +1926,324 @@ out: static inline void __init of_unittest_overlay(void) { } #endif +/* + * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb + * in scripts/Makefile.lib + */ + +#define OVERLAY_INFO_EXTERN(name) \ + extern uint8_t __dtb_##name##_begin[]; \ + extern uint8_t __dtb_##name##_end[] + +#define OVERLAY_INFO(name, expected) \ +{ .dtb_begin = __dtb_##name##_begin, \ + .dtb_end = __dtb_##name##_end, \ + .expected_result = expected, \ +} + +struct overlay_info { + uint8_t *dtb_begin; + uint8_t *dtb_end; + void *data; + struct device_node *np_overlay; + int expected_result; + int overlay_id; +}; + +OVERLAY_INFO_EXTERN(overlay_base); +OVERLAY_INFO_EXTERN(overlay); +OVERLAY_INFO_EXTERN(overlay_bad_phandle); + +#ifdef CONFIG_OF_OVERLAY + +/* order of entries is hard-coded into users of overlays[] */ +static struct overlay_info overlays[] = { + OVERLAY_INFO(overlay_base, -9999), + OVERLAY_INFO(overlay, 0), + OVERLAY_INFO(overlay_bad_phandle, -EINVAL), + {} +}; + +static struct device_node *overlay_base_root; + +/* + * Create base device tree for the overlay unittest. + * + * This is called from very early boot code. + * + * Do as much as possible the same way as done in __unflatten_device_tree + * and other early boot steps for the normal FDT so that the overlay base + * unflattened tree will have the same characteristics as the real tree + * (such as having memory allocated by the early allocator). The goal + * is to test "the real thing" as much as possible, and test "test setup + * code" as little as possible. + * + * Have to stop before resolving phandles, because that uses kmalloc. + */ +void __init unittest_unflatten_overlay_base(void) +{ + struct overlay_info *info; + u32 data_size; + u32 size; + + info = &overlays[0]; + + if (info->expected_result != -9999) { + pr_err("No dtb 'overlay_base' to attach\n"); + return; + } + + data_size = info->dtb_end - info->dtb_begin; + if (!data_size) { + pr_err("No dtb 'overlay_base' to attach\n"); + return; + } + + size = fdt_totalsize(info->dtb_begin); + if (size != data_size) { + pr_err("dtb 'overlay_base' header totalsize != actual size"); + return; + } + + info->data = early_init_dt_alloc_memory_arch(size, + roundup_pow_of_two(FDT_V17_SIZE)); + if (!info->data) { + pr_err("alloc for dtb 'overlay_base' failed"); + return; + } + + memcpy(info->data, info->dtb_begin, size); + + __unflatten_device_tree(info->data, NULL, &info->np_overlay, + early_init_dt_alloc_memory_arch, true); + overlay_base_root = info->np_overlay; +} + +/* + * The purpose of of_unittest_overlay_data_add is to add an + * overlay in the normal fashion. This is a test of the whole + * picture, instead of testing individual elements. + * + * A secondary purpose is to be able to verify that the contents of + * /proc/device-tree/ contains the updated structure and values from + * the overlay. That must be verified separately in user space. + * + * Return 0 on unexpected error. + */ +static int __init overlay_data_add(int onum) +{ + struct overlay_info *info; + int k; + int ret; + u32 size; + u32 size_from_header; + + for (k = 0, info = overlays; info; info++, k++) { + if (k == onum) + break; + } + if (onum > k) + return 0; + + size = info->dtb_end - info->dtb_begin; + if (!size) { + pr_err("no overlay to attach, %d\n", onum); + ret = 0; + } + + size_from_header = fdt_totalsize(info->dtb_begin); + if (size_from_header != size) { + pr_err("overlay header totalsize != actual size, %d", onum); + return 0; + } + + /* + * Must create permanent copy of FDT because of_fdt_unflatten_tree() + * will create pointers to the passed in FDT in the EDT. + */ + info->data = kmemdup(info->dtb_begin, size, GFP_KERNEL); + if (!info->data) { + pr_err("unable to allocate memory for data, %d\n", onum); + return 0; + } + + of_fdt_unflatten_tree(info->data, NULL, &info->np_overlay); + if (!info->np_overlay) { + pr_err("unable to unflatten overlay, %d\n", onum); + ret = 0; + goto out_free_data; + } + of_node_set_flag(info->np_overlay, OF_DETACHED); + + ret = of_resolve_phandles(info->np_overlay); + if (ret) { + pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); + goto out_free_np_overlay; + } + + ret = of_overlay_create(info->np_overlay); + if (ret < 0) { + pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum); + goto out_free_np_overlay; + } else { + info->overlay_id = ret; + ret = 0; + } + + pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); + + goto out; + +out_free_np_overlay: + /* + * info->np_overlay is the unflattened device tree + * It has not been spliced into the live tree. + */ + + /* todo: function to free unflattened device tree */ + +out_free_data: + kfree(info->data); + +out: + return (ret == info->expected_result); +} + +/* + * The purpose of of_unittest_overlay_high_level is to add an overlay + * in the normal fashion. This is a test of the whole picture, + * instead of individual elements. + * + * The first part of the function is _not_ normal overlay usage; it is + * finishing splicing the base overlay device tree into the live tree. + */ +static __init void of_unittest_overlay_high_level(void) +{ + struct device_node *last_sibling; + struct device_node *np; + struct device_node *of_symbols; + 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"); + return; + } + + /* + * Could not fixup phandles in unittest_unflatten_overlay_base() + * because kmalloc() was not yet available. + */ + of_resolve_phandles(overlay_base_root); + + /* + * do not allow overlay_base to duplicate any node already in + * tree, this greatly simplifies the code + */ + + /* + * remove overlay_base_root node "__local_fixups", after + * being used by of_resolve_phandles() + */ + pprev = &overlay_base_root->child; + for (np = overlay_base_root->child; np; np = np->sibling) { + if (!of_node_cmp(np->name, "__local_fixups__")) { + *pprev = np->sibling; + break; + } + pprev = &np->sibling; + } + + /* remove overlay_base_root node "__symbols__" if in live tree */ + of_symbols = of_get_child_by_name(of_root, "__symbols__"); + if (of_symbols) { + /* will have to graft properties from node into live tree */ + pprev = &overlay_base_root->child; + for (np = overlay_base_root->child; np; np = np->sibling) { + if (!of_node_cmp(np->name, "__symbols__")) { + overlay_base_symbols = np; + *pprev = np->sibling; + break; + } + pprev = &np->sibling; + } + } + + for (np = overlay_base_root->child; np; np = np->sibling) { + if (of_get_child_by_name(of_root, np->name)) { + unittest(0, "illegal node name in overlay_base %s", + np->name); + return; + } + } + + /* + * overlay 'overlay_base' is not allowed to have root + * properties, so only need to splice nodes into main device tree. + * + * root node of *overlay_base_root will not be freed, it is lost + * memory. + */ + + for (np = overlay_base_root->child; np; np = np->sibling) + np->parent = of_root; + + mutex_lock(&of_mutex); + + for (last_sibling = np = of_root->child; np; np = np->sibling) + last_sibling = np; + + if (last_sibling) + last_sibling->sibling = overlay_base_root->child; + else + of_root->child = overlay_base_root->child; + + for_each_of_allnodes_from(overlay_base_root, np) + __of_attach_node_sysfs(np); + + if (of_symbols) { + for_each_property_of_node(overlay_base_symbols, prop) { + ret = __of_add_property(of_symbols, prop); + if (ret) { + unittest(0, + "duplicate property '%s' in overlay_base node __symbols__", + prop->name); + goto err_unlock; + } + ret = __of_add_property_sysfs(of_symbols, prop); + if (ret) { + unittest(0, + "unable to add property '%s' in overlay_base node __symbols__ to sysfs", + prop->name); + goto err_unlock; + } + } + } + + mutex_unlock(&of_mutex); + + + /* now do the normal overlay usage test */ + + unittest(overlay_data_add(1), + "Adding overlay 'overlay' failed\n"); + + unittest(overlay_data_add(2), + "Adding overlay 'overlay_bad_phandle' failed\n"); + return; + +err_unlock: + mutex_unlock(&of_mutex); +} + +#else + +static inline __init void of_unittest_overlay_high_level(void) {} + +#endif + static int __init of_unittest(void) { struct device_node *np; @@ -1962,6 +2281,8 @@ static int __init of_unittest(void) /* Double check linkage after removing testcase data */ of_unittest_check_tree_linkage(); + of_unittest_overlay_high_level(); + pr_info("end of unittest - %i passed, %i failed\n", unittest_results.passed, unittest_results.failed); |