[PATCH] of: fix of_tree_for_each_node_from() macro

Boris Brezillon boris.brezillon at free-electrons.com
Tue Apr 26 11:46:06 PDT 2016


of_tree_for_each_node_from() is supposed to iterate over all DT nodes
after the one pointed by the from parameter, but with the current
of_next_node() implementation we cannot access the root node.

Patch of_next_node() to point to root_node when from is NULL.

Doing that also simplifies users of of_tree_for_each_node_from() which
were duplicating the logic to point to the root_node when from is NULL.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
---
Hi Sacha,

Not sure this patch is doing exactly what we want, but it fixes a bug
in the sunxi clk driver I'm working on. This driver declares a
clk provider using CLK_OF_DECLARE() with the SoC compatible (the
compatible attached to the root node), which means the clk core code has
to match the root_node, and with the current of_tree_for_each_node() it
never tests the root_node.

Let me know if you have a different fix.

Thanks,

Boris
---
 drivers/of/base.c | 38 ++++++--------------------------------
 1 file changed, 6 insertions(+), 32 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index aadd228..c2cc0e6 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -30,6 +30,8 @@
 #include <linux/amba/bus.h>
 #include <linux/err.h>
 
+static struct device_node *root_node;
+
 /*
  * Iterate over all nodes of a tree. As a devicetree does not
  * have a dedicated list head, the start node (usually the root
@@ -39,6 +41,9 @@ static inline struct device_node *of_next_node(struct device_node *node)
 {
 	struct device_node *next;
 
+	if (!node)
+		return root_node;
+
 	next = list_first_entry(&node->list, struct device_node, list);
 
 	return next->parent ? next : NULL;
@@ -68,8 +73,6 @@ struct alias_prop {
 
 static LIST_HEAD(aliases_lookup);
 
-static struct device_node *root_node;
-
 static struct device_node *of_aliases;
 
 #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
@@ -277,12 +280,6 @@ struct device_node *of_find_node_by_phandle_from(phandle phandle,
 {
 	struct device_node *node;
 
-	if (!root)
-		root = root_node;
-
-	if (!root)
-		return NULL;
-
 	of_tree_for_each_node_from(node, root)
 		if (node->phandle == phandle)
 			return node;
@@ -309,15 +306,7 @@ EXPORT_SYMBOL(of_find_node_by_phandle);
 phandle of_get_tree_max_phandle(struct device_node *root)
 {
 	struct device_node *n;
-	phandle max;
-
-	if (!root)
-		root = root_node;
-
-	if (!root)
-		return 0;
-
-	max = root->phandle;
+	phandle max = 0;
 
 	of_tree_for_each_node_from(n, root) {
 		if (n->phandle > max)
@@ -430,9 +419,6 @@ struct device_node *of_find_node_by_name(struct device_node *from,
 {
 	struct device_node *np;
 
-	if (!from)
-		from = root_node;
-
 	of_tree_for_each_node_from(np, from)
 		if (np->name && !of_node_cmp(np->name, name))
 			return np;
@@ -458,9 +444,6 @@ struct device_node *of_find_node_by_type(struct device_node *from,
 	const char *device_type;
 	int ret;
 
-	if (!from)
-		from = root_node;
-
 	of_tree_for_each_node_from(np, from) {
 		ret = of_property_read_string(np, "device_type", &device_type);
 		if (!ret && !of_node_cmp(device_type, type))
@@ -489,9 +472,6 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 {
 	struct device_node *np;
 
-	if (!from)
-		from = root_node;
-
 	of_tree_for_each_node_from(np, from)
 		if (of_device_is_compatible(np, compatible))
 			return np;
@@ -516,9 +496,6 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 {
 	struct device_node *np;
 
-	if (!from)
-		from = root_node;
-
 	of_tree_for_each_node_from(np, from) {
 		struct property *pp = of_find_property(np, prop_name, NULL);
 		if (pp)
@@ -572,9 +549,6 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 	if (match)
 		*match = NULL;
 
-	if (!from)
-		from = root_node;
-
 	of_tree_for_each_node_from(np, from) {
 		const struct of_device_id *m = of_match_node(matches, np);
 		if (m) {
-- 
2.7.4




More information about the barebox mailing list