aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/vexpress-sysreg.c2
-rw-r--r--drivers/of/base.c53
-rw-r--r--drivers/of/dynamic.c13
-rw-r--r--drivers/of/fdt.c30
-rw-r--r--drivers/of/pdt.c27
-rw-r--r--drivers/of/selftest.c71
6 files changed, 88 insertions, 108 deletions
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 9e21e4fc9599..8f43ab8fd2d6 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -223,7 +223,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
223 vexpress_config_set_master(vexpress_sysreg_get_master()); 223 vexpress_config_set_master(vexpress_sysreg_get_master());
224 224
225 /* Confirm board type against DT property, if available */ 225 /* Confirm board type against DT property, if available */
226 if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { 226 if (of_property_read_u32(of_root, "arm,hbi", &dt_hbi) == 0) {
227 u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER); 227 u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER);
228 u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK; 228 u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
229 229
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3823edf2d012..1f61a908a767 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -32,8 +32,8 @@
32 32
33LIST_HEAD(aliases_lookup); 33LIST_HEAD(aliases_lookup);
34 34
35struct device_node *of_allnodes; 35struct device_node *of_root;
36EXPORT_SYMBOL(of_allnodes); 36EXPORT_SYMBOL(of_root);
37struct device_node *of_chosen; 37struct device_node *of_chosen;
38struct device_node *of_aliases; 38struct device_node *of_aliases;
39struct device_node *of_stdout; 39struct device_node *of_stdout;
@@ -48,7 +48,7 @@ struct kset *of_kset;
48 */ 48 */
49DEFINE_MUTEX(of_mutex); 49DEFINE_MUTEX(of_mutex);
50 50
51/* use when traversing tree through the allnext, child, sibling, 51/* use when traversing tree through the child, sibling,
52 * or parent members of struct device_node. 52 * or parent members of struct device_node.
53 */ 53 */
54DEFINE_RAW_SPINLOCK(devtree_lock); 54DEFINE_RAW_SPINLOCK(devtree_lock);
@@ -204,7 +204,7 @@ static int __init of_init(void)
204 mutex_unlock(&of_mutex); 204 mutex_unlock(&of_mutex);
205 205
206 /* Symlink in /proc as required by userspace ABI */ 206 /* Symlink in /proc as required by userspace ABI */
207 if (of_allnodes) 207 if (of_root)
208 proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 208 proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
209 209
210 return 0; 210 return 0;
@@ -245,6 +245,23 @@ struct property *of_find_property(const struct device_node *np,
245} 245}
246EXPORT_SYMBOL(of_find_property); 246EXPORT_SYMBOL(of_find_property);
247 247
248struct device_node *__of_find_all_nodes(struct device_node *prev)
249{
250 struct device_node *np;
251 if (!prev) {
252 np = of_root;
253 } else if (prev->child) {
254 np = prev->child;
255 } else {
256 /* Walk back up looking for a sibling, or the end of the structure */
257 np = prev;
258 while (np->parent && !np->sibling)
259 np = np->parent;
260 np = np->sibling; /* Might be null at the end of the tree */
261 }
262 return np;
263}
264
248/** 265/**
249 * of_find_all_nodes - Get next node in global list 266 * of_find_all_nodes - Get next node in global list
250 * @prev: Previous node or NULL to start iteration 267 * @prev: Previous node or NULL to start iteration
@@ -259,10 +276,8 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
259 unsigned long flags; 276 unsigned long flags;
260 277
261 raw_spin_lock_irqsave(&devtree_lock, flags); 278 raw_spin_lock_irqsave(&devtree_lock, flags);
262 np = prev ? prev->allnext : of_allnodes; 279 np = __of_find_all_nodes(prev);
263 for (; np != NULL; np = np->allnext) 280 of_node_get(np);
264 if (of_node_get(np))
265 break;
266 of_node_put(prev); 281 of_node_put(prev);
267 raw_spin_unlock_irqrestore(&devtree_lock, flags); 282 raw_spin_unlock_irqrestore(&devtree_lock, flags);
268 return np; 283 return np;
@@ -736,7 +751,7 @@ struct device_node *of_find_node_by_path(const char *path)
736 unsigned long flags; 751 unsigned long flags;
737 752
738 if (strcmp(path, "/") == 0) 753 if (strcmp(path, "/") == 0)
739 return of_node_get(of_allnodes); 754 return of_node_get(of_root);
740 755
741 /* The path could begin with an alias */ 756 /* The path could begin with an alias */
742 if (*path != '/') { 757 if (*path != '/') {
@@ -761,7 +776,7 @@ struct device_node *of_find_node_by_path(const char *path)
761 /* Step down the tree matching path components */ 776 /* Step down the tree matching path components */
762 raw_spin_lock_irqsave(&devtree_lock, flags); 777 raw_spin_lock_irqsave(&devtree_lock, flags);
763 if (!np) 778 if (!np)
764 np = of_node_get(of_allnodes); 779 np = of_node_get(of_root);
765 while (np && *path == '/') { 780 while (np && *path == '/') {
766 path++; /* Increment past '/' delimiter */ 781 path++; /* Increment past '/' delimiter */
767 np = __of_find_node_by_path(np, path); 782 np = __of_find_node_by_path(np, path);
@@ -790,8 +805,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
790 unsigned long flags; 805 unsigned long flags;
791 806
792 raw_spin_lock_irqsave(&devtree_lock, flags); 807 raw_spin_lock_irqsave(&devtree_lock, flags);
793 np = from ? from->allnext : of_allnodes; 808 for_each_of_allnodes_from(from, np)
794 for (; np; np = np->allnext)
795 if (np->name && (of_node_cmp(np->name, name) == 0) 809 if (np->name && (of_node_cmp(np->name, name) == 0)
796 && of_node_get(np)) 810 && of_node_get(np))
797 break; 811 break;
@@ -820,8 +834,7 @@ struct device_node *of_find_node_by_type(struct device_node *from,
820 unsigned long flags; 834 unsigned long flags;
821 835
822 raw_spin_lock_irqsave(&devtree_lock, flags); 836 raw_spin_lock_irqsave(&devtree_lock, flags);
823 np = from ? from->allnext : of_allnodes; 837 for_each_of_allnodes_from(from, np)
824 for (; np; np = np->allnext)
825 if (np->type && (of_node_cmp(np->type, type) == 0) 838 if (np->type && (of_node_cmp(np->type, type) == 0)
826 && of_node_get(np)) 839 && of_node_get(np))
827 break; 840 break;
@@ -852,12 +865,10 @@ struct device_node *of_find_compatible_node(struct device_node *from,
852 unsigned long flags; 865 unsigned long flags;
853 866
854 raw_spin_lock_irqsave(&devtree_lock, flags); 867 raw_spin_lock_irqsave(&devtree_lock, flags);
855 np = from ? from->allnext : of_allnodes; 868 for_each_of_allnodes_from(from, np)
856 for (; np; np = np->allnext) {
857 if (__of_device_is_compatible(np, compatible, type, NULL) && 869 if (__of_device_is_compatible(np, compatible, type, NULL) &&
858 of_node_get(np)) 870 of_node_get(np))
859 break; 871 break;
860 }
861 of_node_put(from); 872 of_node_put(from);
862 raw_spin_unlock_irqrestore(&devtree_lock, flags); 873 raw_spin_unlock_irqrestore(&devtree_lock, flags);
863 return np; 874 return np;
@@ -884,8 +895,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
884 unsigned long flags; 895 unsigned long flags;
885 896
886 raw_spin_lock_irqsave(&devtree_lock, flags); 897 raw_spin_lock_irqsave(&devtree_lock, flags);
887 np = from ? from->allnext : of_allnodes; 898 for_each_of_allnodes_from(from, np) {
888 for (; np; np = np->allnext) {
889 for (pp = np->properties; pp; pp = pp->next) { 899 for (pp = np->properties; pp; pp = pp->next) {
890 if (of_prop_cmp(pp->name, prop_name) == 0) { 900 if (of_prop_cmp(pp->name, prop_name) == 0) {
891 of_node_get(np); 901 of_node_get(np);
@@ -967,8 +977,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
967 *match = NULL; 977 *match = NULL;
968 978
969 raw_spin_lock_irqsave(&devtree_lock, flags); 979 raw_spin_lock_irqsave(&devtree_lock, flags);
970 np = from ? from->allnext : of_allnodes; 980 for_each_of_allnodes_from(from, np) {
971 for (; np; np = np->allnext) {
972 m = __of_match_node(matches, np); 981 m = __of_match_node(matches, np);
973 if (m && of_node_get(np)) { 982 if (m && of_node_get(np)) {
974 if (match) 983 if (match)
@@ -1025,7 +1034,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
1025 return NULL; 1034 return NULL;
1026 1035
1027 raw_spin_lock_irqsave(&devtree_lock, flags); 1036 raw_spin_lock_irqsave(&devtree_lock, flags);
1028 for (np = of_allnodes; np; np = np->allnext) 1037 for_each_of_allnodes(np)
1029 if (np->phandle == handle) 1038 if (np->phandle == handle)
1030 break; 1039 break;
1031 of_node_get(np); 1040 of_node_get(np);
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index f297891d8529..da2509d639c8 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -117,8 +117,6 @@ void __of_attach_node(struct device_node *np)
117 117
118 np->child = NULL; 118 np->child = NULL;
119 np->sibling = np->parent->child; 119 np->sibling = np->parent->child;
120 np->allnext = np->parent->allnext;
121 np->parent->allnext = np;
122 np->parent->child = np; 120 np->parent->child = np;
123 of_node_clear_flag(np, OF_DETACHED); 121 of_node_clear_flag(np, OF_DETACHED);
124} 122}
@@ -154,17 +152,6 @@ void __of_detach_node(struct device_node *np)
154 if (WARN_ON(!parent)) 152 if (WARN_ON(!parent))
155 return; 153 return;
156 154
157 if (of_allnodes == np)
158 of_allnodes = np->allnext;
159 else {
160 struct device_node *prev;
161 for (prev = of_allnodes;
162 prev->allnext != np;
163 prev = prev->allnext)
164 ;
165 prev->allnext = np->allnext;
166 }
167
168 if (parent->child == np) 155 if (parent->child == np)
169 parent->child = np->sibling; 156 parent->child = np->sibling;
170 else { 157 else {
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index d1ffca8b34ea..1d30b9f96466 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -145,15 +145,15 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
145 * @mem: Memory chunk to use for allocating device nodes and properties 145 * @mem: Memory chunk to use for allocating device nodes and properties
146 * @p: pointer to node in flat tree 146 * @p: pointer to node in flat tree
147 * @dad: Parent struct device_node 147 * @dad: Parent struct device_node
148 * @allnextpp: pointer to ->allnext from last allocated device_node
149 * @fpsize: Size of the node path up at the current depth. 148 * @fpsize: Size of the node path up at the current depth.
150 */ 149 */
151static void * unflatten_dt_node(void *blob, 150static void * unflatten_dt_node(void *blob,
152 void *mem, 151 void *mem,
153 int *poffset, 152 int *poffset,
154 struct device_node *dad, 153 struct device_node *dad,
155 struct device_node ***allnextpp, 154 struct device_node **nodepp,
156 unsigned long fpsize) 155 unsigned long fpsize,
156 bool dryrun)
157{ 157{
158 const __be32 *p; 158 const __be32 *p;
159 struct device_node *np; 159 struct device_node *np;
@@ -200,7 +200,7 @@ static void * unflatten_dt_node(void *blob,
200 200
201 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, 201 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
202 __alignof__(struct device_node)); 202 __alignof__(struct device_node));
203 if (allnextpp) { 203 if (!dryrun) {
204 char *fn; 204 char *fn;
205 of_node_init(np); 205 of_node_init(np);
206 np->full_name = fn = ((char *)np) + sizeof(*np); 206 np->full_name = fn = ((char *)np) + sizeof(*np);
@@ -222,8 +222,6 @@ static void * unflatten_dt_node(void *blob,
222 memcpy(fn, pathp, l); 222 memcpy(fn, pathp, l);
223 223
224 prev_pp = &np->properties; 224 prev_pp = &np->properties;
225 **allnextpp = np;
226 *allnextpp = &np->allnext;
227 if (dad != NULL) { 225 if (dad != NULL) {
228 np->parent = dad; 226 np->parent = dad;
229 /* we temporarily use the next field as `last_child'*/ 227 /* we temporarily use the next field as `last_child'*/
@@ -254,7 +252,7 @@ static void * unflatten_dt_node(void *blob,
254 has_name = 1; 252 has_name = 1;
255 pp = unflatten_dt_alloc(&mem, sizeof(struct property), 253 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
256 __alignof__(struct property)); 254 __alignof__(struct property));
257 if (allnextpp) { 255 if (!dryrun) {
258 /* We accept flattened tree phandles either in 256 /* We accept flattened tree phandles either in
259 * ePAPR-style "phandle" properties, or the 257 * ePAPR-style "phandle" properties, or the
260 * legacy "linux,phandle" properties. If both 258 * legacy "linux,phandle" properties. If both
@@ -296,7 +294,7 @@ static void * unflatten_dt_node(void *blob,
296 sz = (pa - ps) + 1; 294 sz = (pa - ps) + 1;
297 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, 295 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
298 __alignof__(struct property)); 296 __alignof__(struct property));
299 if (allnextpp) { 297 if (!dryrun) {
300 pp->name = "name"; 298 pp->name = "name";
301 pp->length = sz; 299 pp->length = sz;
302 pp->value = pp + 1; 300 pp->value = pp + 1;
@@ -308,7 +306,7 @@ static void * unflatten_dt_node(void *blob,
308 (char *)pp->value); 306 (char *)pp->value);
309 } 307 }
310 } 308 }
311 if (allnextpp) { 309 if (!dryrun) {
312 *prev_pp = NULL; 310 *prev_pp = NULL;
313 np->name = of_get_property(np, "name", NULL); 311 np->name = of_get_property(np, "name", NULL);
314 np->type = of_get_property(np, "device_type", NULL); 312 np->type = of_get_property(np, "device_type", NULL);
@@ -324,11 +322,13 @@ static void * unflatten_dt_node(void *blob,
324 if (depth < 0) 322 if (depth < 0)
325 depth = 0; 323 depth = 0;
326 while (*poffset > 0 && depth > old_depth) 324 while (*poffset > 0 && depth > old_depth)
327 mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, 325 mem = unflatten_dt_node(blob, mem, poffset, np, NULL,
328 fpsize); 326 fpsize, dryrun);
329 327
330 if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) 328 if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
331 pr_err("unflatten: error %d processing FDT\n", *poffset); 329 pr_err("unflatten: error %d processing FDT\n", *poffset);
330 if (nodepp)
331 *nodepp = np;
332 332
333 return mem; 333 return mem;
334} 334}
@@ -352,7 +352,6 @@ static void __unflatten_device_tree(void *blob,
352 unsigned long size; 352 unsigned long size;
353 int start; 353 int start;
354 void *mem; 354 void *mem;
355 struct device_node **allnextp = mynodes;
356 355
357 pr_debug(" -> unflatten_device_tree()\n"); 356 pr_debug(" -> unflatten_device_tree()\n");
358 357
@@ -373,7 +372,7 @@ static void __unflatten_device_tree(void *blob,
373 372
374 /* First pass, scan for size */ 373 /* First pass, scan for size */
375 start = 0; 374 start = 0;
376 size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0); 375 size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true);
377 size = ALIGN(size, 4); 376 size = ALIGN(size, 4);
378 377
379 pr_debug(" size is %lx, allocating...\n", size); 378 pr_debug(" size is %lx, allocating...\n", size);
@@ -388,11 +387,10 @@ static void __unflatten_device_tree(void *blob,
388 387
389 /* Second pass, do actual unflattening */ 388 /* Second pass, do actual unflattening */
390 start = 0; 389 start = 0;
391 unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); 390 unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
392 if (be32_to_cpup(mem + size) != 0xdeadbeef) 391 if (be32_to_cpup(mem + size) != 0xdeadbeef)
393 pr_warning("End of tree marker overwritten: %08x\n", 392 pr_warning("End of tree marker overwritten: %08x\n",
394 be32_to_cpup(mem + size)); 393 be32_to_cpup(mem + size));
395 *allnextp = NULL;
396 394
397 pr_debug(" <- unflatten_device_tree()\n"); 395 pr_debug(" <- unflatten_device_tree()\n");
398} 396}
@@ -1041,7 +1039,7 @@ bool __init early_init_dt_scan(void *params)
1041 */ 1039 */
1042void __init unflatten_device_tree(void) 1040void __init unflatten_device_tree(void)
1043{ 1041{
1044 __unflatten_device_tree(initial_boot_params, &of_allnodes, 1042 __unflatten_device_tree(initial_boot_params, &of_root,
1045 early_init_dt_alloc_memory_arch); 1043 early_init_dt_alloc_memory_arch);
1046 1044
1047 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ 1045 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 36b4035881b0..d2acae825af9 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -25,8 +25,7 @@
25 25
26static struct of_pdt_ops *of_pdt_prom_ops __initdata; 26static struct of_pdt_ops *of_pdt_prom_ops __initdata;
27 27
28void __initdata (*of_pdt_build_more)(struct device_node *dp, 28void __initdata (*of_pdt_build_more)(struct device_node *dp);
29 struct device_node ***nextp);
30 29
31#if defined(CONFIG_SPARC) 30#if defined(CONFIG_SPARC)
32unsigned int of_pdt_unique_id __initdata; 31unsigned int of_pdt_unique_id __initdata;
@@ -192,8 +191,7 @@ static struct device_node * __init of_pdt_create_node(phandle node,
192} 191}
193 192
194static struct device_node * __init of_pdt_build_tree(struct device_node *parent, 193static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
195 phandle node, 194 phandle node)
196 struct device_node ***nextp)
197{ 195{
198 struct device_node *ret = NULL, *prev_sibling = NULL; 196 struct device_node *ret = NULL, *prev_sibling = NULL;
199 struct device_node *dp; 197 struct device_node *dp;
@@ -210,16 +208,12 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
210 ret = dp; 208 ret = dp;
211 prev_sibling = dp; 209 prev_sibling = dp;
212 210
213 *(*nextp) = dp;
214 *nextp = &dp->allnext;
215
216 dp->full_name = of_pdt_build_full_name(dp); 211 dp->full_name = of_pdt_build_full_name(dp);
217 212
218 dp->child = of_pdt_build_tree(dp, 213 dp->child = of_pdt_build_tree(dp, of_pdt_prom_ops->getchild(node));
219 of_pdt_prom_ops->getchild(node), nextp);
220 214
221 if (of_pdt_build_more) 215 if (of_pdt_build_more)
222 of_pdt_build_more(dp, nextp); 216 of_pdt_build_more(dp);
223 217
224 node = of_pdt_prom_ops->getsibling(node); 218 node = of_pdt_prom_ops->getsibling(node);
225 } 219 }
@@ -234,20 +228,17 @@ static void * __init kernel_tree_alloc(u64 size, u64 align)
234 228
235void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) 229void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
236{ 230{
237 struct device_node **nextp;
238
239 BUG_ON(!ops); 231 BUG_ON(!ops);
240 of_pdt_prom_ops = ops; 232 of_pdt_prom_ops = ops;
241 233
242 of_allnodes = of_pdt_create_node(root_node, NULL); 234 of_root = of_pdt_create_node(root_node, NULL);
243#if defined(CONFIG_SPARC) 235#if defined(CONFIG_SPARC)
244 of_allnodes->path_component_name = ""; 236 of_root->path_component_name = "";
245#endif 237#endif
246 of_allnodes->full_name = "/"; 238 of_root->full_name = "/";
247 239
248 nextp = &of_allnodes->allnext; 240 of_root->child = of_pdt_build_tree(of_root,
249 of_allnodes->child = of_pdt_build_tree(of_allnodes, 241 of_pdt_prom_ops->getchild(of_root->phandle));
250 of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp);
251 242
252 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ 243 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
253 of_alias_scan(kernel_tree_alloc); 244 of_alias_scan(kernel_tree_alloc);
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 11b873c54a77..bf7d99317a94 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -148,7 +148,7 @@ static void __init of_selftest_dynamic(void)
148 148
149static int __init of_selftest_check_node_linkage(struct device_node *np) 149static int __init of_selftest_check_node_linkage(struct device_node *np)
150{ 150{
151 struct device_node *child, *allnext_index = np; 151 struct device_node *child;
152 int count = 0, rc; 152 int count = 0, rc;
153 153
154 for_each_child_of_node(np, child) { 154 for_each_child_of_node(np, child) {
@@ -158,14 +158,6 @@ static int __init of_selftest_check_node_linkage(struct device_node *np)
158 return -EINVAL; 158 return -EINVAL;
159 } 159 }
160 160
161 while (allnext_index && allnext_index != child)
162 allnext_index = allnext_index->allnext;
163 if (allnext_index != child) {
164 pr_err("Node %s is ordered differently in sibling and allnode lists\n",
165 child->name);
166 return -EINVAL;
167 }
168
169 rc = of_selftest_check_node_linkage(child); 161 rc = of_selftest_check_node_linkage(child);
170 if (rc < 0) 162 if (rc < 0)
171 return rc; 163 return rc;
@@ -180,12 +172,12 @@ static void __init of_selftest_check_tree_linkage(void)
180 struct device_node *np; 172 struct device_node *np;
181 int allnode_count = 0, child_count; 173 int allnode_count = 0, child_count;
182 174
183 if (!of_allnodes) 175 if (!of_root)
184 return; 176 return;
185 177
186 for_each_of_allnodes(np) 178 for_each_of_allnodes(np)
187 allnode_count++; 179 allnode_count++;
188 child_count = of_selftest_check_node_linkage(of_allnodes); 180 child_count = of_selftest_check_node_linkage(of_root);
189 181
190 selftest(child_count > 0, "Device node data structure is corrupted\n"); 182 selftest(child_count > 0, "Device node data structure is corrupted\n");
191 selftest(child_count == allnode_count, "allnodes list size (%i) doesn't match" 183 selftest(child_count == allnode_count, "allnodes list size (%i) doesn't match"
@@ -775,33 +767,29 @@ static void update_node_properties(struct device_node *np,
775 */ 767 */
776static int attach_node_and_children(struct device_node *np) 768static int attach_node_and_children(struct device_node *np)
777{ 769{
778 struct device_node *next, *root = np, *dup; 770 struct device_node *next, *dup, *child;
779 771
780 /* skip root node */ 772 dup = of_find_node_by_path(np->full_name);
781 np = np->child; 773 if (dup) {
782 /* storing a copy in temporary node */ 774 update_node_properties(np, dup);
783 dup = np; 775 return 0;
776 }
784 777
785 while (dup) { 778 /* Children of the root need to be remembered for removal */
779 if (np->parent == of_root) {
786 if (WARN_ON(last_node_index >= NO_OF_NODES)) 780 if (WARN_ON(last_node_index >= NO_OF_NODES))
787 return -EINVAL; 781 return -EINVAL;
788 nodes[last_node_index++] = dup; 782 nodes[last_node_index++] = np;
789 dup = dup->sibling;
790 } 783 }
791 dup = NULL;
792 784
793 while (np) { 785 child = np->child;
794 next = np->allnext; 786 np->child = NULL;
795 dup = of_find_node_by_path(np->full_name); 787 np->sibling = NULL;
796 if (dup) 788 of_attach_node(np);
797 update_node_properties(np, dup); 789 while (child) {
798 else { 790 next = child->sibling;
799 np->child = NULL; 791 attach_node_and_children(child);
800 if (np->parent == root) 792 child = next;
801 np->parent = of_allnodes;
802 of_attach_node(np);
803 }
804 np = next;
805 } 793 }
806 794
807 return 0; 795 return 0;
@@ -846,10 +834,10 @@ static int __init selftest_data_add(void)
846 return -EINVAL; 834 return -EINVAL;
847 } 835 }
848 836
849 if (!of_allnodes) { 837 if (!of_root) {
850 /* enabling flag for removing nodes */ 838 /* enabling flag for removing nodes */
851 selftest_live_tree = true; 839 selftest_live_tree = true;
852 of_allnodes = selftest_data_node; 840 of_root = selftest_data_node;
853 841
854 for_each_of_allnodes(np) 842 for_each_of_allnodes(np)
855 __of_attach_node_sysfs(np); 843 __of_attach_node_sysfs(np);
@@ -859,7 +847,14 @@ static int __init selftest_data_add(void)
859 } 847 }
860 848
861 /* attach the sub-tree to live tree */ 849 /* attach the sub-tree to live tree */
862 return attach_node_and_children(selftest_data_node); 850 np = selftest_data_node->child;
851 while (np) {
852 struct device_node *next = np->sibling;
853 np->parent = of_root;
854 attach_node_and_children(np);
855 np = next;
856 }
857 return 0;
863} 858}
864 859
865/** 860/**
@@ -889,10 +884,10 @@ static void selftest_data_remove(void)
889 of_node_put(of_chosen); 884 of_node_put(of_chosen);
890 of_aliases = NULL; 885 of_aliases = NULL;
891 of_chosen = NULL; 886 of_chosen = NULL;
892 for_each_child_of_node(of_allnodes, np) 887 for_each_child_of_node(of_root, np)
893 detach_node_and_children(np); 888 detach_node_and_children(np);
894 __of_detach_node_sysfs(of_allnodes); 889 __of_detach_node_sysfs(of_root);
895 of_allnodes = NULL; 890 of_root = NULL;
896 return; 891 return;
897 } 892 }
898 893