diff options
Diffstat (limited to 'drivers/of/selftest.c')
-rw-r--r-- | drivers/of/selftest.c | 71 |
1 files changed, 33 insertions, 38 deletions
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 | ||
149 | static int __init of_selftest_check_node_linkage(struct device_node *np) | 149 | static 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 | */ |
776 | static int attach_node_and_children(struct device_node *np) | 768 | static 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 | ||