Skip to content

Commit c22e650

Browse files
committed
of: Make of_find_node_by_path() handle /aliases
Make of_find_node_by_path() handle aliases as prefixes. To make this work the name search is refactored to search by path component instead of by full string. This should be a more efficient search, and it makes it possible to start a search at a subnode of a tree. Signed-off-by: David Daney <[email protected]> Signed-off-by: Pantelis Antoniou <[email protected]> [grant.likely: Rework to not require allocating at runtime] Acked-by: Rob Herring <[email protected]> Signed-off-by: Grant Likely <[email protected]>
1 parent 0d0e02d commit c22e650

File tree

1 file changed

+61
-6
lines changed

1 file changed

+61
-6
lines changed

drivers/of/base.c

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -783,23 +783,78 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
783783
}
784784
EXPORT_SYMBOL(of_get_child_by_name);
785785

786+
static struct device_node *__of_find_node_by_path(struct device_node *parent,
787+
const char *path)
788+
{
789+
struct device_node *child;
790+
int len = strchrnul(path, '/') - path;
791+
792+
if (!len)
793+
return NULL;
794+
795+
__for_each_child_of_node(parent, child) {
796+
const char *name = strrchr(child->full_name, '/');
797+
if (WARN(!name, "malformed device_node %s\n", child->full_name))
798+
continue;
799+
name++;
800+
if (strncmp(path, name, len) == 0 && (strlen(name) == len))
801+
return child;
802+
}
803+
return NULL;
804+
}
805+
786806
/**
787807
* of_find_node_by_path - Find a node matching a full OF path
788-
* @path: The full path to match
808+
* @path: Either the full path to match, or if the path does not
809+
* start with '/', the name of a property of the /aliases
810+
* node (an alias). In the case of an alias, the node
811+
* matching the alias' value will be returned.
812+
*
813+
* Valid paths:
814+
* /foo/bar Full path
815+
* foo Valid alias
816+
* foo/bar Valid alias + relative path
789817
*
790818
* Returns a node pointer with refcount incremented, use
791819
* of_node_put() on it when done.
792820
*/
793821
struct device_node *of_find_node_by_path(const char *path)
794822
{
795-
struct device_node *np = of_allnodes;
823+
struct device_node *np = NULL;
824+
struct property *pp;
796825
unsigned long flags;
797826

827+
if (strcmp(path, "/") == 0)
828+
return of_node_get(of_allnodes);
829+
830+
/* The path could begin with an alias */
831+
if (*path != '/') {
832+
char *p = strchrnul(path, '/');
833+
int len = p - path;
834+
835+
/* of_aliases must not be NULL */
836+
if (!of_aliases)
837+
return NULL;
838+
839+
for_each_property_of_node(of_aliases, pp) {
840+
if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
841+
np = of_find_node_by_path(pp->value);
842+
break;
843+
}
844+
}
845+
if (!np)
846+
return NULL;
847+
path = p;
848+
}
849+
850+
/* Step down the tree matching path components */
798851
raw_spin_lock_irqsave(&devtree_lock, flags);
799-
for (; np; np = np->allnext) {
800-
if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
801-
&& of_node_get(np))
802-
break;
852+
if (!np)
853+
np = of_node_get(of_allnodes);
854+
while (np && *path == '/') {
855+
path++; /* Increment past '/' delimiter */
856+
np = __of_find_node_by_path(np, path);
857+
path = strchrnul(path, '/');
803858
}
804859
raw_spin_unlock_irqrestore(&devtree_lock, flags);
805860
return np;

0 commit comments

Comments
 (0)