[PATCH] of: Make of_find_node_by_path() handle /aliases

From: Pantelis Antoniou
Date: Tue Mar 18 2014 - 17:52:47 EST


Make of_find_node_by_path() handle aliases as prefixes.

Originally by David Daney <ddaney@xxxxxxxxxxxxxxxxxx>, but
reworked according to remark by Grant Likely.

Handles all cases without allocating memory as requested by
Grant Likely <grant.likely@xxxxxxxxxx>

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@xxxxxxxxxxxx>
---
drivers/of/base.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 65 insertions(+), 4 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 7083fad..19bcdb4 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -773,22 +773,83 @@ EXPORT_SYMBOL(of_get_child_by_name);
/**
* of_find_node_by_path - Find a node matching a full OF path
* @path: The full path to match
+ * @path: Either the full path to match, or if the path does not
+ * start with '/', the name of a property of the /aliases
+ * node (an alias). In the case of an alias, the node
+ * matching the alias' value will be returned.
+ *
+ * Valid paths:
+ * /foo/bar Full path
+ * foo Valid alias
+ * foo/bar Valid alias + relative path
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_by_path(const char *path)
{
- struct device_node *np = of_allnodes;
+ struct device_node *np = NULL;
+ int len;
+ const char *p = NULL;
+ struct property *prop;
unsigned long flags;

+ /* under lock (not very nice) */
raw_spin_lock_irqsave(&devtree_lock, flags);
- for (; np; np = np->allnext) {
- if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
- && of_node_get(np))
+
+ len = strlen(path);
+
+ /* path begins with an alias */
+ if (path[0] != '/') {
+
+ /* now find the relative path (if any)*/
+ p = strchr(path, '/');
+ if (p != NULL)
+ len = p - path;
+
+ /* of_aliases must not be NULL */
+ if (!of_aliases)
+ goto out;
+
+ /* find matching alias */
+ for_each_property_of_node(of_aliases, prop)
+ if (strlen(prop->name) == len &&
+ strncmp(prop->name, path, len) == 0)
+ break;
+
+ /* not found; bail */
+ if (prop == NULL)
+ goto out;
+
+ path = prop->value;
+ }
+
+ /* path lookup */
+ for_each_of_allnodes(np) {
+
+ if (!np->full_name)
+ continue;
+
+ if (p == NULL) {
+ /* full component */
+ if (strcasecmp(np->full_name, path) != 0)
+ continue;
+ } else {
+ /* last component (including '/') */
+ if (strncasecmp(np->full_name, path, len) != 0)
+ continue;
+
+ if (strcasecmp(np->full_name + len, p) != 0)
+ continue;
+ }
+
+ if (of_node_get(np))
break;
}
+
+out:
raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
return np;
}
EXPORT_SYMBOL(of_find_node_by_path);
--
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/