aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/of_selftest.txt20
-rw-r--r--Documentation/devicetree/todo.txt1
-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
-rw-r--r--include/linux/of.h11
-rw-r--r--include/linux/of_pdt.h3
10 files changed, 98 insertions, 133 deletions
diff --git a/Documentation/devicetree/of_selftest.txt b/Documentation/devicetree/of_selftest.txt
index 1e3d5c92b5e3..57a808b588bf 100644
--- a/Documentation/devicetree/of_selftest.txt
+++ b/Documentation/devicetree/of_selftest.txt
@@ -63,7 +63,6 @@ struct device_node {
63 struct device_node *parent; 63 struct device_node *parent;
64 struct device_node *child; 64 struct device_node *child;
65 struct device_node *sibling; 65 struct device_node *sibling;
66 struct device_node *allnext; /* next in list of all nodes */
67 ... 66 ...
68 }; 67 };
69 68
@@ -99,12 +98,6 @@ child11 -> sibling12 -> sibling13 -> sibling14 -> null
99Figure 1: Generic structure of un-flattened device tree 98Figure 1: Generic structure of un-flattened device tree
100 99
101 100
102*allnext: it is used to link all the nodes of DT into a list. So, for the
103 above tree the list would be as follows:
104
105root->child1->child11->sibling12->sibling13->child131->sibling14->sibling2->
106child21->sibling22->sibling23->sibling3->child31->sibling32->sibling4->null
107
108Before executing OF selftest, it is required to attach the test data to 101Before executing OF selftest, it is required to attach the test data to
109machine's device tree (if present). So, when selftest_data_add() is called, 102machine's device tree (if present). So, when selftest_data_add() is called,
110at first it reads the flattened device tree data linked into the kernel image 103at first it reads the flattened device tree data linked into the kernel image
@@ -131,11 +124,6 @@ root ('/')
131 test-child01 null null null 124 test-child01 null null null
132 125
133 126
134allnext list:
135
136root->testcase-data->test-child0->test-child01->test-sibling1->test-sibling2
137->test-sibling3->null
138
139Figure 2: Example test data tree to be attached to live tree. 127Figure 2: Example test data tree to be attached to live tree.
140 128
141According to the scenario above, the live tree is already present so it isn't 129According to the scenario above, the live tree is already present so it isn't
@@ -204,8 +192,6 @@ detached and then moving up the parent nodes are removed, and eventually the
204whole tree). selftest_data_remove() calls detach_node_and_children() that uses 192whole tree). selftest_data_remove() calls detach_node_and_children() that uses
205of_detach_node() to detach the nodes from the live device tree. 193of_detach_node() to detach the nodes from the live device tree.
206 194
207To detach a node, of_detach_node() first updates all_next linked list, by 195To detach a node, of_detach_node() either updates the child pointer of given
208attaching the previous node's allnext to current node's allnext pointer. And 196node's parent to its sibling or attaches the previous sibling to the given
209then, it either updates the child pointer of given node's parent to its 197node's sibling, as appropriate. That is it :)
210sibling or attaches the previous sibling to the given node's sibling, as
211appropriate. That is it :)
diff --git a/Documentation/devicetree/todo.txt b/Documentation/devicetree/todo.txt
index c3cf0659bd19..b5139d1de811 100644
--- a/Documentation/devicetree/todo.txt
+++ b/Documentation/devicetree/todo.txt
@@ -2,7 +2,6 @@ Todo list for devicetree:
2 2
3=== General structure === 3=== General structure ===
4- Switch from custom lists to (h)list_head for nodes and properties structure 4- Switch from custom lists to (h)list_head for nodes and properties structure
5- Remove of_allnodes list and iterate using list of child nodes alone
6 5
7=== CONFIG_OF_DYNAMIC === 6=== CONFIG_OF_DYNAMIC ===
8- Switch to RCU for tree updates and get rid of global spinlock 7- Switch to RCU for tree updates and get rid of global spinlock
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
diff --git a/include/linux/of.h b/include/linux/of.h
index 30912939a610..f54da3b699a8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -56,7 +56,6 @@ struct device_node {
56 struct device_node *child; 56 struct device_node *child;
57 struct device_node *sibling; 57 struct device_node *sibling;
58 struct device_node *next; /* next device of same type */ 58 struct device_node *next; /* next device of same type */
59 struct device_node *allnext; /* next in list of all nodes */
60 struct kobject kobj; 59 struct kobject kobj;
61 unsigned long _flags; 60 unsigned long _flags;
62 void *data; 61 void *data;
@@ -108,7 +107,7 @@ static inline void of_node_put(struct device_node *node) { }
108#ifdef CONFIG_OF 107#ifdef CONFIG_OF
109 108
110/* Pointer for first entry in chain of all nodes. */ 109/* Pointer for first entry in chain of all nodes. */
111extern struct device_node *of_allnodes; 110extern struct device_node *of_root;
112extern struct device_node *of_chosen; 111extern struct device_node *of_chosen;
113extern struct device_node *of_aliases; 112extern struct device_node *of_aliases;
114extern struct device_node *of_stdout; 113extern struct device_node *of_stdout;
@@ -116,7 +115,7 @@ extern raw_spinlock_t devtree_lock;
116 115
117static inline bool of_have_populated_dt(void) 116static inline bool of_have_populated_dt(void)
118{ 117{
119 return of_allnodes != NULL; 118 return of_root != NULL;
120} 119}
121 120
122static inline bool of_node_is_root(const struct device_node *node) 121static inline bool of_node_is_root(const struct device_node *node)
@@ -160,6 +159,7 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
160 clear_bit(flag, &p->_flags); 159 clear_bit(flag, &p->_flags);
161} 160}
162 161
162extern struct device_node *__of_find_all_nodes(struct device_node *prev);
163extern struct device_node *of_find_all_nodes(struct device_node *prev); 163extern struct device_node *of_find_all_nodes(struct device_node *prev);
164 164
165/* 165/*
@@ -215,8 +215,9 @@ static inline const char *of_node_full_name(const struct device_node *np)
215 return np ? np->full_name : "<no-node>"; 215 return np ? np->full_name : "<no-node>";
216} 216}
217 217
218#define for_each_of_allnodes(dn) \ 218#define for_each_of_allnodes_from(from, dn) \
219 for (dn = of_allnodes; dn; dn = dn->allnext) 219 for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn))
220#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)
220extern struct device_node *of_find_node_by_name(struct device_node *from, 221extern struct device_node *of_find_node_by_name(struct device_node *from,
221 const char *name); 222 const char *name);
222extern struct device_node *of_find_node_by_type(struct device_node *from, 223extern struct device_node *of_find_node_by_type(struct device_node *from,
diff --git a/include/linux/of_pdt.h b/include/linux/of_pdt.h
index c65a18a0cfdf..7e09244bb679 100644
--- a/include/linux/of_pdt.h
+++ b/include/linux/of_pdt.h
@@ -39,7 +39,6 @@ extern void *prom_early_alloc(unsigned long size);
39/* for building the device tree */ 39/* for building the device tree */
40extern void of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops); 40extern void of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops);
41 41
42extern void (*of_pdt_build_more)(struct device_node *dp, 42extern void (*of_pdt_build_more)(struct device_node *dp);
43 struct device_node ***nextp);
44 43
45#endif /* _LINUX_OF_PDT_H */ 44#endif /* _LINUX_OF_PDT_H */