All of lore.kernel.org
 help / color / mirror / Atom feed
From: NISHIMOTO Hiroki <hiroki.nishimoto.if@gmail.com>
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
	barebox@lists.infradead.org
Subject: Re: [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API
Date: Wed, 03 Jul 2013 03:35:01 +0900	[thread overview]
Message-ID: <51D31D55.8000302@gmail.com> (raw)

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

             reply	other threads:[~2013-07-02 18:43 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-02 18:35 NISHIMOTO Hiroki [this message]
2013-07-03 21:14 ` [PATCH 11/22] OF: base: import of_find_matching_node_and_match from Linux OF API 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51D31D55.8000302@gmail.com \
    --to=hiroki.nishimoto.if@gmail.com \
    --cc=barebox@lists.infradead.org \
    --cc=sebastian.hesselbarth@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.