All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API
  2013-06-18 17:29 [PATCH 00/22] Barebox OF API fixes, sync, and cleanup Sebastian Hesselbarth
@ 2013-06-18 17:29 ` Sebastian Hesselbarth
  0 siblings, 0 replies; 3+ messages in thread
From: Sebastian Hesselbarth @ 2013-06-18 17:29 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: barebox

This imports of_find_matching_node_and_match and corresponding helpers
from Linux OF API.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Cc: barebox@lists.infradead.org
---
 drivers/of/base.c |   37 +++++++++++++++++++++++++++++++++++++
 include/of.h      |   24 ++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 50a3c22..218cb5a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -389,6 +389,43 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 	return NULL;
 }
 
+/**
+ *	of_find_matching_node_and_match - Find a node based on an of_device_id
+ *					  match table.
+ *	@from:		The node to start searching from or NULL, the node
+ *			you pass will not be searched, only the next one
+ *			will; typically, you pass what the previous call
+ *			returned.
+ *	@matches:	array of of device match structures to search in
+ *	@match		Updated to point at the matches entry which matched
+ *
+ *	Returns a pointer to the node found or NULL.
+ */
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+					const struct of_device_id *matches,
+					const struct of_device_id **match)
+{
+	struct device_node *np;
+
+	if (match)
+		*match = NULL;
+
+	if (!from)
+		from = root_node;
+
+	of_tree_for_each_node(np, from) {
+		const struct of_device_id *m = of_match_node(matches, np);
+		if (m) {
+			if (match)
+				*match = m;
+			return np;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_matching_node_and_match);
+
 int of_match(struct device_d *dev, struct driver_d *drv)
 {
 	const struct of_device_id *id;
diff --git a/include/of.h b/include/of.h
index e170e2b..c21e73d 100644
--- a/include/of.h
+++ b/include/of.h
@@ -187,6 +187,10 @@ extern struct device_node *of_find_node_by_name(struct device_node *from,
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
+extern struct device_node *of_find_matching_node_and_match(
+	struct device_node *from,
+	const struct of_device_id *matches,
+	const struct of_device_id **match);
 extern int of_device_is_available(const struct device_node *device);
 
 extern void of_alias_scan(void);
@@ -259,6 +263,14 @@ static inline struct device_node *of_find_compatible_node(
 	return NULL;
 }
 
+static inline struct device_node *of_find_matching_node_and_match(
+					struct device_node *from,
+					const struct of_device_id *matches,
+					const struct of_device_id **match)
+{
+	return NULL;
+}
+
 static inline int of_device_is_available(const struct device_node *device)
 {
 	return 0;
@@ -285,5 +297,17 @@ static inline const char *of_alias_get(struct device_node *np)
 #define for_each_compatible_node(dn, type, compatible) \
 	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
 	     dn = of_find_compatible_node(dn, type, compatible))
+static inline struct device_node *of_find_matching_node(
+	struct device_node *from,
+	const struct of_device_id *matches)
+{
+	return of_find_matching_node_and_match(from, matches, NULL);
+}
+#define for_each_matching_node(dn, matches) \
+	for (dn = of_find_matching_node(NULL, matches); dn; \
+	     dn = of_find_matching_node(dn, matches))
+#define for_each_matching_node_and_match(dn, matches, match) \
+	for (dn = of_find_matching_node_and_match(NULL, matches, match); \
+	     dn; dn = of_find_matching_node_and_match(dn, matches, match))
 
 #endif /* __OF_H */
-- 
1.7.2.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API
@ 2013-07-02 18:35 NISHIMOTO Hiroki
  2013-07-03 21:14 ` Sebastian Hesselbarth
  0 siblings, 1 reply; 3+ messages in thread
From: NISHIMOTO Hiroki @ 2013-07-02 18:35 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox

Hi,

on master/next branch,

of_find_matching_node_and_match macro can make infinite loop.

This is because, of_tree_for_each_node traverse all nodes each time.
But a callee of of_find_matching_node_and_match,
such as for_each_matching_node, calls it by changing "from" arg.
So if "matches" have two or more nodes, previously matched node can be re-matched.

Below change can fix the issue.
Or is it better to port node->allnext from linux kernel?

Signed-off-by: NISHIMOTO Hiroki <hiroki.nishimoto.if@gmail.com>
---
 drivers/of/base.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 63ff647..36774de 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -36,6 +36,9 @@
 #define of_tree_for_each_node(node, root) \
 	list_for_each_entry(node, &root->list, list)
 
+#define of_get_next_node(np) \
+	list_first_entry(&np->list, typeof(*np), list)
+
 /**
  * struct alias_prop - Alias property in 'aliases' node
  * @link:	List node to link the structure in aliases_lookup list
@@ -444,17 +447,20 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 	if (match)
 		*match = NULL;
 
-	if (!from)
-		from = root_node;
+	np = from ? of_get_next_node(from) : root_node;
 
-	of_tree_for_each_node(np, from) {
+	if (from != NULL && np == root_node)
+		return NULL;
+
+	do {
 		const struct of_device_id *m = of_match_node(matches, np);
 		if (m) {
 			if (match)
 				*match = m;
 			return np;
 		}
-	}
+		np = of_get_next_node(np);
+	} while (np != root_node);
 
 	return NULL;
 }
-- 
1.8.1.2


> This imports of_find_matching_node_and_match and corresponding helpers
> from Linux OF API.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@xxxxxxxxx>
> ---
> Cc: barebox@xxxxxxxxxxxxxxxxxxx
> ---
>  drivers/of/base.c |   37 +++++++++++++++++++++++++++++++++++++
>  include/of.h      |   24 ++++++++++++++++++++++++
>  2 files changed, 61 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 50a3c22..218cb5a 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -389,6 +389,43 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
>  	return NULL;
>  }
>  
> +/**
> + *	of_find_matching_node_and_match - Find a node based on an of_device_id
> + *					  match table.
> + *	@from:		The node to start searching from or NULL, the node
> + *			you pass will not be searched, only the next one
> + *			will; typically, you pass what the previous call
> + *			returned.
> + *	@matches:	array of of device match structures to search in
> + *	@match		Updated to point at the matches entry which matched
> + *
> + *	Returns a pointer to the node found or NULL.
> + */
> +struct device_node *of_find_matching_node_and_match(struct device_node *from,
> +					const struct of_device_id *matches,
> +					const struct of_device_id **match)
> +{
> +	struct device_node *np;
> +
> +	if (match)
> +		*match = NULL;
> +
> +	if (!from)
> +		from = root_node;
> +
> +	of_tree_for_each_node(np, from) {
> +		const struct of_device_id *m = of_match_node(matches, np);
> +		if (m) {
> +			if (match)
> +				*match = m;
> +			return np;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(of_find_matching_node_and_match);
> +
>  int of_match(struct device_d *dev, struct driver_d *drv)
>  {
>  	const struct of_device_id *id;
> diff --git a/include/of.h b/include/of.h
> index e170e2b..c21e73d 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -187,6 +187,10 @@ extern struct device_node *of_find_node_by_name(struct device_node *from,
>  extern struct device_node *of_find_node_by_path(const char *path);
>  extern struct device_node *of_find_compatible_node(struct device_node *from,
>  	const char *type, const char *compat);
> +extern struct device_node *of_find_matching_node_and_match(
> +	struct device_node *from,
> +	const struct of_device_id *matches,
> +	const struct of_device_id **match);
>  extern int of_device_is_available(const struct device_node *device);
>  
>  extern void of_alias_scan(void);
> @@ -259,6 +263,14 @@ static inline struct device_node *of_find_compatible_node(
>  	return NULL;
>  }
>  
> +static inline struct device_node *of_find_matching_node_and_match(
> +					struct device_node *from,
> +					const struct of_device_id *matches,
> +					const struct of_device_id **match)
> +{
> +	return NULL;
> +}
> +
>  static inline int of_device_is_available(const struct device_node *device)
>  {
>  	return 0;
> @@ -285,5 +297,17 @@ static inline const char *of_alias_get(struct device_node *np)
>  #define for_each_compatible_node(dn, type, compatible) \
>  	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
>  	     dn = of_find_compatible_node(dn, type, compatible))
> +static inline struct device_node *of_find_matching_node(
> +	struct device_node *from,
> +	const struct of_device_id *matches)
> +{
> +	return of_find_matching_node_and_match(from, matches, NULL);
> +}
> +#define for_each_matching_node(dn, matches) \
> +	for (dn = of_find_matching_node(NULL, matches); dn; \
> +	     dn = of_find_matching_node(dn, matches))
> +#define for_each_matching_node_and_match(dn, matches, match) \
> +	for (dn = of_find_matching_node_and_match(NULL, matches, match); \
> +	     dn; dn = of_find_matching_node_and_match(dn, matches, match))
>  
>  #endif /* __OF_H */
> -- 
> 1.7.2.5



_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API
  2013-07-02 18:35 [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API NISHIMOTO Hiroki
@ 2013-07-03 21:14 ` Sebastian Hesselbarth
  0 siblings, 0 replies; 3+ messages in thread
From: Sebastian Hesselbarth @ 2013-07-03 21:14 UTC (permalink / raw)
  To: NISHIMOTO Hiroki; +Cc: barebox

On 07/02/2013 08:35 PM, NISHIMOTO Hiroki wrote:
> on master/next branch,
>
> of_find_matching_node_and_match macro can make infinite loop.

Hiroki,

I confirmed that infinite loop but there are more functions
that suffer from this infinite loop.

> This is because, of_tree_for_each_node traverse all nodes each time.
> But a callee of of_find_matching_node_and_match,
> such as for_each_matching_node, calls it by changing "from" arg.
> So if "matches" have two or more nodes, previously matched node can be re-matched.
>
> Below change can fix the issue.

@Sascha: please confirm the below. It is what I understand from your
last comments about OF API improvements.

Actually, root_node is only the list head for the currently active
device tree. There can be other device trees you want to use the
of_for_each_.. on, so we need to find another way to check for the
list head of the tree the "from" node is in.

 From what I can see from linux linked lists API, there is no safe
way to determine the start of a linked list without knowing what
has been the first list node in the first place.

Sascha knows barebox struct device_node lists for sure, maybe he
can point us to the best way to solve this?

Sebastian

> Or is it better to port node->allnext from linux kernel?
>
> Signed-off-by: NISHIMOTO Hiroki<hiroki.nishimoto.if@gmail.com>
> ---
>   drivers/of/base.c | 14 ++++++++++----
>   1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 63ff647..36774de 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -36,6 +36,9 @@
>   #define of_tree_for_each_node(node, root) \
>   	list_for_each_entry(node,&root->list, list)
>
> +#define of_get_next_node(np) \
> +	list_first_entry(&np->list, typeof(*np), list)
> +
>   /**
>    * struct alias_prop - Alias property in 'aliases' node
>    * @link:	List node to link the structure in aliases_lookup list
> @@ -444,17 +447,20 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>   	if (match)
>   		*match = NULL;
>
> -	if (!from)
> -		from = root_node;
> +	np = from ? of_get_next_node(from) : root_node;
>
> -	of_tree_for_each_node(np, from) {
> +	if (from != NULL&&  np == root_node)
> +		return NULL;
> +
> +	do {
>   		const struct of_device_id *m = of_match_node(matches, np);
>   		if (m) {
>   			if (match)
>   				*match = m;
>   			return np;
>   		}
> -	}
> +		np = of_get_next_node(np);
> +	} while (np != root_node);
>
>   	return NULL;
>   }


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-07-03 21:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-02 18:35 [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API NISHIMOTO Hiroki
2013-07-03 21:14 ` Sebastian Hesselbarth
  -- strict thread matches above, loose matches on Subject: below --
2013-06-18 17:29 [PATCH 00/22] Barebox OF API fixes, sync, and cleanup Sebastian Hesselbarth
2013-06-18 17:29 ` [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API Sebastian Hesselbarth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.