diff options
author | Grant Likely <grant.likely@linaro.org> | 2014-10-03 16:28:27 +0100 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-11-04 13:29:38 +0000 |
commit | 5063e25a302e6a83f6590d9a06bd5f6400b17430 (patch) | |
tree | bd6aafd28fb65ea19cd1535fd9a53263b42a68c0 /drivers/of/base.c | |
parent | e7a00e4210e4cc980e3ba67ec7301af54061d14b (diff) | |
download | lwn-5063e25a302e6a83f6590d9a06bd5f6400b17430.tar.gz lwn-5063e25a302e6a83f6590d9a06bd5f6400b17430.zip |
of: Eliminate of_allnodes list
The device tree structure is composed of two lists; the 'allnodes' list
which is a singly linked list containing every node in the tree, and the
child->parent structure where each parent node has a singly linked list
of children. All of the data in the allnodes list can be easily
reproduced with the parent-child lists, so of_allnodes is actually
unnecessary. Remove it entirely which saves a bit of memory and
simplifies the data structure quite a lot.
Signed-off-by: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Gaurav Minocha <gaurav.minocha.os@gmail.com>
Cc: Pantelis Antoniou <pantelis@pantelis.antoniou@konsulko.com>
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 53 |
1 files changed, 31 insertions, 22 deletions
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 @@ LIST_HEAD(aliases_lookup); -struct device_node *of_allnodes; -EXPORT_SYMBOL(of_allnodes); +struct device_node *of_root; +EXPORT_SYMBOL(of_root); struct device_node *of_chosen; struct device_node *of_aliases; struct device_node *of_stdout; @@ -48,7 +48,7 @@ struct kset *of_kset; */ DEFINE_MUTEX(of_mutex); -/* use when traversing tree through the allnext, child, sibling, +/* use when traversing tree through the child, sibling, * or parent members of struct device_node. */ DEFINE_RAW_SPINLOCK(devtree_lock); @@ -204,7 +204,7 @@ static int __init of_init(void) mutex_unlock(&of_mutex); /* Symlink in /proc as required by userspace ABI */ - if (of_allnodes) + if (of_root) proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); return 0; @@ -245,6 +245,23 @@ struct property *of_find_property(const struct device_node *np, } EXPORT_SYMBOL(of_find_property); +struct device_node *__of_find_all_nodes(struct device_node *prev) +{ + struct device_node *np; + if (!prev) { + np = of_root; + } else if (prev->child) { + np = prev->child; + } else { + /* Walk back up looking for a sibling, or the end of the structure */ + np = prev; + while (np->parent && !np->sibling) + np = np->parent; + np = np->sibling; /* Might be null at the end of the tree */ + } + return np; +} + /** * of_find_all_nodes - Get next node in global list * @prev: Previous node or NULL to start iteration @@ -259,10 +276,8 @@ struct device_node *of_find_all_nodes(struct device_node *prev) unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = prev ? prev->allnext : of_allnodes; - for (; np != NULL; np = np->allnext) - if (of_node_get(np)) - break; + np = __of_find_all_nodes(prev); + of_node_get(np); of_node_put(prev); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; @@ -736,7 +751,7 @@ struct device_node *of_find_node_by_path(const char *path) unsigned long flags; if (strcmp(path, "/") == 0) - return of_node_get(of_allnodes); + return of_node_get(of_root); /* The path could begin with an alias */ if (*path != '/') { @@ -761,7 +776,7 @@ struct device_node *of_find_node_by_path(const char *path) /* Step down the tree matching path components */ raw_spin_lock_irqsave(&devtree_lock, flags); if (!np) - np = of_node_get(of_allnodes); + np = of_node_get(of_root); while (np && *path == '/') { path++; /* Increment past '/' delimiter */ np = __of_find_node_by_path(np, path); @@ -790,8 +805,7 @@ struct device_node *of_find_node_by_name(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) + for_each_of_allnodes_from(from, np) if (np->name && (of_node_cmp(np->name, name) == 0) && of_node_get(np)) break; @@ -820,8 +834,7 @@ struct device_node *of_find_node_by_type(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) + for_each_of_allnodes_from(from, np) if (np->type && (of_node_cmp(np->type, type) == 0) && of_node_get(np)) break; @@ -852,12 +865,10 @@ struct device_node *of_find_compatible_node(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) if (__of_device_is_compatible(np, compatible, type, NULL) && of_node_get(np)) break; - } of_node_put(from); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; @@ -884,8 +895,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) { for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, prop_name) == 0) { of_node_get(np); @@ -967,8 +977,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, *match = NULL; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) { m = __of_match_node(matches, np); if (m && of_node_get(np)) { if (match) @@ -1025,7 +1034,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) return NULL; raw_spin_lock_irqsave(&devtree_lock, flags); - for (np = of_allnodes; np; np = np->allnext) + for_each_of_allnodes(np) if (np->phandle == handle) break; of_node_get(np); |