* 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
* [PATCH 00/22] Barebox OF API fixes, sync, and cleanup
@ 2013-06-18 17:29 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
0 siblings, 1 reply; 3+ messages in thread
From: Sebastian Hesselbarth @ 2013-06-18 17:29 UTC (permalink / raw)
To: Sebastian Hesselbarth; +Cc: barebox
This is a quite large patch set to make Barebox OF API more behave
like Linux OF API. Also, it prepares Barebox to reuse Linux OF address
handling and drivers/of/of_* helpers soon.
The patch set is roughly divided into 5 sections:
(1) Patch 1 introduces case-insensitive string compare functions that will
be used later during import of Linux OF API functions.
(2) Patches 2 and 3 fix some bugs in existing OF API functions.
(3) Patches 4-8 synchronize existing OF API functions with Linux OF API
counterparts.
(4) Patches 9-18 import API functions from Linux OF API or introduce new
functions based on existing Barebox OF API functions.
(5) Patches 19-22 convert to new API functions and remove now obsolete
functions. Further, it cleans up existing OF include, by providing
OFTREE prototypes and !OFTREE bogus stubs.
I have tested the patch set with both CONFIG_OFTREE set and not set.
The patch set applied to barebox/next can also be found at
git://github.com/shesselba/barebox-dove.git barebox-of-sync-v1
Sebastian Hesselbarth (22):
lib: string: import case-insensitive string compare
OF: base: bail out early on missing matches for of_match_node
OF: base: also update property length on of_property_write_u32
OF: base: export of_alias_scan
OF: base: convert strcmp to default string compare functions
OF: base: sync of_find_property with linux OF API
OF: base: sync of_find_node_by_path with linux OF API
OF: base: rename of_node_disabled to of_device_is_available
OF: base: import of_find_node_by_name from Linux OF API
OF: base: import of_find_compatible_node from Linux OF API
OF: base: import of_find_matching_node_and_match from Linux OF API
OF: base: import of_find_node_with_property from Linux OF API
OF: base: import parent/child functions from Linux OF API
OF: base: import of_property_read_* helpers from Linux OF API
OF: base: import of_parse_phandle from Linux OF API
OF: base: import parse phandle functions from Linux OF API
OF: base: introduce property write for bool, u8, u16, and u64
OF: base: import property iterators from Linux OF API
OF: base: remove of_tree_for_each_node from public API
OF: base: remove of_find_child_by_name
OF: base: convert and remove device_node_for_nach_child
OF: base: cleanup base function include
arch/arm/boards/at91sam9x5ek/hw_version.c | 10 +-
arch/arm/boards/highbank/init.c | 20 +-
arch/ppc/mach-mpc5xxx/cpu.c | 4 +-
commands/of_node.c | 2 +-
commands/of_property.c | 12 +-
commands/oftree.c | 11 +-
common/oftree.c | 2 +-
drivers/i2c/i2c.c | 2 +-
drivers/mfd/stmpe-i2c.c | 7 +-
drivers/of/base.c | 1234 +++++++++++++++++++++++------
drivers/of/fdt.c | 14 +-
drivers/of/gpio.c | 9 +-
drivers/of/of_net.c | 6 +-
drivers/of/partition.c | 2 +-
drivers/pinctrl/pinctrl.c | 4 +-
drivers/spi/spi.c | 12 +-
drivers/usb/imx/chipidea-imx.c | 14 +-
include/linux/string.h | 9 +
include/of.h | 616 ++++++++++++--
lib/string.c | 60 ++
net/eth.c | 2 +-
21 files changed, 1624 insertions(+), 428 deletions(-)
---
Cc: barebox@lists.infradead.org
--
1.7.2.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread* [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
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.