diff options
author | Grant Likely <grant.likely@linaro.org> | 2014-10-03 11:28:27 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-11-04 08:29:38 -0500 |
commit | 5063e25a302e6a83f6590d9a06bd5f6400b17430 (patch) | |
tree | bd6aafd28fb65ea19cd1535fd9a53263b42a68c0 /drivers/of/base.c | |
parent | e7a00e4210e4cc980e3ba67ec7301af54061d14b (diff) |
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 @@ | |||
32 | 32 | ||
33 | LIST_HEAD(aliases_lookup); | 33 | LIST_HEAD(aliases_lookup); |
34 | 34 | ||
35 | struct device_node *of_allnodes; | 35 | struct device_node *of_root; |
36 | EXPORT_SYMBOL(of_allnodes); | 36 | EXPORT_SYMBOL(of_root); |
37 | struct device_node *of_chosen; | 37 | struct device_node *of_chosen; |
38 | struct device_node *of_aliases; | 38 | struct device_node *of_aliases; |
39 | struct device_node *of_stdout; | 39 | struct device_node *of_stdout; |
@@ -48,7 +48,7 @@ struct kset *of_kset; | |||
48 | */ | 48 | */ |
49 | DEFINE_MUTEX(of_mutex); | 49 | DEFINE_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 | */ |
54 | DEFINE_RAW_SPINLOCK(devtree_lock); | 54 | DEFINE_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 | } |
246 | EXPORT_SYMBOL(of_find_property); | 246 | EXPORT_SYMBOL(of_find_property); |
247 | 247 | ||
248 | struct 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); |