diff mbox series

[v6,2/5] device property: Introduce fwnode_for_each_parent_node()

Message ID 20220408184844.22829-2-andriy.shevchenko@linux.intel.com
State Superseded
Headers show
Series [v6,1/5] device property: Allow error pointer to be passed to fwnode APIs | expand

Commit Message

Andy Shevchenko April 8, 2022, 6:48 p.m. UTC
In a few cases the functionality of fwnode_for_each_parent_node()
is already in use. Introduce a common helper macro for it.

It may be used by others as well in the future.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
v6: added tag (Sakari)
 drivers/base/property.c  | 56 +++++++++++++++++++++-------------------
 include/linux/property.h |  9 +++++--
 2 files changed, 36 insertions(+), 29 deletions(-)

Comments

Doug Anderson April 29, 2022, 11:45 p.m. UTC | #1
Hi,

On Fri, Apr 8, 2022 at 11:50 AM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> In a few cases the functionality of fwnode_for_each_parent_node()
> is already in use. Introduce a common helper macro for it.
>
> It may be used by others as well in the future.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
> v6: added tag (Sakari)
>  drivers/base/property.c  | 56 +++++++++++++++++++++-------------------
>  include/linux/property.h |  9 +++++--
>  2 files changed, 36 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 6ecc1398b0ba..f0ac31d28798 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -596,17 +596,17 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
>   */
>  struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
>  {
> +       struct fwnode_handle *parent;
>         struct device *dev;
>
> -       fwnode_handle_get(fwnode);
> -       do {
> -               fwnode = fwnode_get_next_parent(fwnode);
> -               if (!fwnode)
> -                       return NULL;
> +       fwnode_for_each_parent_node(fwnode, parent) {
>                 dev = get_dev_from_fwnode(fwnode);

Breadcrumbs in case anyone else ends up at this patch due to a bisect,
like I just did. The above should have been changed to
"get_dev_from_fwnode(parent);" in this patch. Fix posted at:

https://lore.kernel.org/r/20220429164325.1.I2a3b980ea051e59140227999f0f0ca16f1125768@changeid
diff mbox series

Patch

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 6ecc1398b0ba..f0ac31d28798 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -596,17 +596,17 @@  EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
  */
 struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
 {
+	struct fwnode_handle *parent;
 	struct device *dev;
 
-	fwnode_handle_get(fwnode);
-	do {
-		fwnode = fwnode_get_next_parent(fwnode);
-		if (!fwnode)
-			return NULL;
+	fwnode_for_each_parent_node(fwnode, parent) {
 		dev = get_dev_from_fwnode(fwnode);
-	} while (!dev);
-	fwnode_handle_put(fwnode);
-	return dev;
+		if (dev) {
+			fwnode_handle_put(parent);
+			return dev;
+		}
+	}
+	return NULL;
 }
 
 /**
@@ -617,13 +617,11 @@  struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
  */
 unsigned int fwnode_count_parents(const struct fwnode_handle *fwnode)
 {
-	struct fwnode_handle *__fwnode;
-	unsigned int count;
-
-	__fwnode = fwnode_get_parent(fwnode);
+	struct fwnode_handle *parent;
+	unsigned int count = 0;
 
-	for (count = 0; __fwnode; count++)
-		__fwnode = fwnode_get_next_parent(__fwnode);
+	fwnode_for_each_parent_node(fwnode, parent)
+		count++;
 
 	return count;
 }
@@ -644,15 +642,16 @@  EXPORT_SYMBOL_GPL(fwnode_count_parents);
 struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
 					    unsigned int depth)
 {
-	fwnode_handle_get(fwnode);
+	struct fwnode_handle *parent;
 
-	do {
-		if (depth-- == 0)
-			break;
-		fwnode = fwnode_get_next_parent(fwnode);
-	} while (fwnode);
+	if (depth == 0)
+		return fwnode_handle_get(fwnode);
 
-	return fwnode;
+	fwnode_for_each_parent_node(fwnode, parent) {
+		if (--depth == 0)
+			return parent;
+	}
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
 
@@ -669,17 +668,20 @@  EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
 bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
 				  struct fwnode_handle *test_child)
 {
+	struct fwnode_handle *parent;
+
 	if (IS_ERR_OR_NULL(test_ancestor))
 		return false;
 
-	fwnode_handle_get(test_child);
-	do {
-		if (test_child == test_ancestor) {
-			fwnode_handle_put(test_child);
+	if (test_child == test_ancestor)
+		return true;
+
+	fwnode_for_each_parent_node(test_child, parent) {
+		if (parent == test_ancestor) {
+			fwnode_handle_put(parent);
 			return true;
 		}
-		test_child = fwnode_get_next_parent(test_child);
-	} while (test_child);
+	}
 	return false;
 }
 
diff --git a/include/linux/property.h b/include/linux/property.h
index 4cd4b326941f..15d6863ae962 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -83,9 +83,14 @@  struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
 
 const char *fwnode_get_name(const struct fwnode_handle *fwnode);
 const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode);
+
 struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
-struct fwnode_handle *fwnode_get_next_parent(
-	struct fwnode_handle *fwnode);
+struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode);
+
+#define fwnode_for_each_parent_node(fwnode, parent)		\
+	for (parent = fwnode_get_parent(fwnode); parent;	\
+	     parent = fwnode_get_next_parent(parent))
+
 struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode);
 unsigned int fwnode_count_parents(const struct fwnode_handle *fwn);
 struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn,