Skip to content

Commit 36156f9

Browse files
jhovoldrobherring
authored andcommitted
of: add helper to lookup compatible child node
Add of_get_compatible_child() helper that can be used to lookup compatible child nodes. Several drivers currently use of_find_compatible_node() to lookup child nodes while failing to notice that the of_find_ functions search the entire tree depth-first (from a given start node) and therefore can match unrelated nodes. The fact that these functions also drop a reference to the node they start searching from (e.g. the parent node) is typically also overlooked, something which can lead to use-after-free bugs. Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Rob Herring <robh@kernel.org>
1 parent 5b394b2 commit 36156f9

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

drivers/of/base.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,31 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
719719
}
720720
EXPORT_SYMBOL(of_get_next_available_child);
721721

722+
/**
723+
* of_get_compatible_child - Find compatible child node
724+
* @parent: parent node
725+
* @compatible: compatible string
726+
*
727+
* Lookup child node whose compatible property contains the given compatible
728+
* string.
729+
*
730+
* Returns a node pointer with refcount incremented, use of_node_put() on it
731+
* when done; or NULL if not found.
732+
*/
733+
struct device_node *of_get_compatible_child(const struct device_node *parent,
734+
const char *compatible)
735+
{
736+
struct device_node *child;
737+
738+
for_each_child_of_node(parent, child) {
739+
if (of_device_is_compatible(child, compatible))
740+
break;
741+
}
742+
743+
return child;
744+
}
745+
EXPORT_SYMBOL(of_get_compatible_child);
746+
722747
/**
723748
* of_get_child_by_name - Find the child node by name for a given parent
724749
* @node: parent node

include/linux/of.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
290290
extern struct device_node *of_get_next_available_child(
291291
const struct device_node *node, struct device_node *prev);
292292

293+
extern struct device_node *of_get_compatible_child(const struct device_node *parent,
294+
const char *compatible);
293295
extern struct device_node *of_get_child_by_name(const struct device_node *node,
294296
const char *name);
295297

@@ -632,6 +634,12 @@ static inline bool of_have_populated_dt(void)
632634
return false;
633635
}
634636

637+
static inline struct device_node *of_get_compatible_child(const struct device_node *parent,
638+
const char *compatible)
639+
{
640+
return NULL;
641+
}
642+
635643
static inline struct device_node *of_get_child_by_name(
636644
const struct device_node *node,
637645
const char *name)

0 commit comments

Comments
 (0)