diff mbox series

[2/2,resend] OF: add for_each_port_of_node()

Message ID 87o9aa0whf.wl-kuninori.morimoto.gx@renesas.com
State Rejected, archived
Headers show
Series OF: add functions for port | expand

Checks

Context Check Description
robh/checkpatch success

Commit Message

Kuninori Morimoto Nov. 28, 2018, 2:34 a.m. UTC
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

We have for_each_endpoint_of_node(), but don't have port version of it.
It is useful if we have it. This patch adds it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 drivers/of/property.c    | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/of_graph.h | 20 ++++++++++++++++++++
 2 files changed, 57 insertions(+)

Comments

Rob Herring Nov. 28, 2018, 4:37 a.m. UTC | #1
On Tue, Nov 27, 2018 at 8:34 PM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
>
>
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
>
> We have for_each_endpoint_of_node(), but don't have port version of it.
> It is useful if we have it. This patch adds it.

I'd like to see the user for this first.

Generally, I don't think iterating over port or endpoint nodes is the
right way to walk the graph. A given port address has a defined
function and you should be requesting the specific ports.

>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---
>  drivers/of/property.c    | 37 +++++++++++++++++++++++++++++++++++++
>  include/linux/of_graph.h | 20 ++++++++++++++++++++
>  2 files changed, 57 insertions(+)
>
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 3db01ee..2ec4c95 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -585,6 +585,43 @@ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
>  EXPORT_SYMBOL(of_graph_get_port_by_id);
>
>  /**
> + * of_graph_get_next_port() - get next port node
> + * @parent: pointer to the parent device node
> + * @prev: previous port node, or NULL to get first
> + *
> + * Return: An 'port' node pointer with refcount incremented. Refcount
> + * of the passed @prev node is decremented.
> + */
> +struct device_node *of_graph_get_next_port(const struct device_node *parent,
> +                                          struct device_node *prev)
> +{
> +       struct device_node *port;
> +
> +       if (!parent)
> +               return NULL;
> +
> +       if (!prev) {
> +               struct device_node *node;
> +
> +               node = of_get_child_by_name(parent, "ports");
> +               if (node)
> +                       parent = node;
> +               port = NULL;
> +       } else {
> +               port = prev;
> +       }
> +
> +       do {
> +               port = of_get_next_child(parent, port);
> +               if (!port)
> +                       return NULL;
> +       } while (of_node_cmp(port->name, "port"));

Use of_node_name_eq()

> +
> +       return port;
> +}
> +EXPORT_SYMBOL(of_graph_get_next_port);
> +
> +/**
>   * of_graph_get_next_endpoint() - get next endpoint node
>   * @parent: pointer to the parent device node
>   * @prev: previous endpoint node, or NULL to get first
> diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
> index 7fbbf80..d219cc7 100644
> --- a/include/linux/of_graph.h
> +++ b/include/linux/of_graph.h
> @@ -27,6 +27,17 @@ struct of_endpoint {
>  };
>
>  /**
> + * for_each_port_of_node - iterate over every port in a device node
> + * @parent: parent device node containing ports
> + * @child: loop variable pointing to the current port node
> + *
> + * When breaking out of the loop, of_node_put(child) has to be called manually.
> + */
> +#define for_each_port_of_node(parent, child) \
> +       for (child = of_graph_get_next_port(parent, NULL); child != NULL; \
> +            child = of_graph_get_next_port(parent, child))
> +
> +/**
>   * for_each_endpoint_of_node - iterate over every endpoint in a device node
>   * @parent: parent device node containing ports and endpoints
>   * @child: loop variable pointing to the current endpoint node
> @@ -44,6 +55,8 @@ int of_graph_parse_endpoint(const struct device_node *node,
>                                 struct of_endpoint *endpoint);
>  int of_graph_get_endpoint_count(const struct device_node *np);
>  struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
> +struct device_node *of_graph_get_next_port(const struct device_node *parent,
> +                                              struct device_node *previous);
>  struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
>                                         struct device_node *previous);
>  struct device_node *of_graph_get_endpoint_by_regs(
> @@ -75,6 +88,13 @@ static inline struct device_node *of_graph_get_port_by_id(
>         return NULL;
>  }
>
> +static inline struct device_node *of_graph_get_next_port(
> +                                       const struct device_node *parent,
> +                                       struct device_node *previous)
> +{
> +       return NULL;
> +}
> +
>  static inline struct device_node *of_graph_get_next_endpoint(
>                                         const struct device_node *parent,
>                                         struct device_node *previous)
> --
> 2.7.4
>
Kuninori Morimoto Nov. 28, 2018, 6:54 a.m. UTC | #2
Hi Rob again

> > +       do {
> > +               port = of_get_next_child(parent, port);
> > +               if (!port)
> > +                       return NULL;
> > +       } while (of_node_cmp(port->name, "port"));
> 
> Use of_node_name_eq()

I tried this, but unfortunately it seems of_node_name_eq()
is not good match to this purpose.
Because it try to check with "port@n".

# I noticed that I can cleanup this patch to more simpler.
# I want to send v2 patch if this patch is not rejected
# Please let me know

Best regards
---
Kuninori Morimoto
Rob Herring Nov. 28, 2018, 3:46 p.m. UTC | #3
On Tue, Nov 27, 2018 at 10:46 PM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
>
>
> Hi Rob
>
> Thank you for reviewing
>
> > I'd like to see the user for this first.
> >
> > Generally, I don't think iterating over port or endpoint nodes is the
> > right way to walk the graph. A given port address has a defined
> > function and you should be requesting the specific ports.
>
> I attached patch which is using for_each_port_of_node().
> I want to know "specified" port location.
>
> -------------
> From 1abf55f28cc12c207bce646e579f19ded117d5c6 Mon Sep 17 00:00:00 2001
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Date: Thu, 15 Nov 2018 11:18:31 +0900
> Subject: [PATCH] ASoC: simple-card-utils: fixup asoc_simple_card_get_dai_id()
>  counting
>
> asoc_simple_card_get_dai_id() returns DAI ID, but it is based on
> DT node's "endpoint" count.
> Almost all cases 1 port has 1 endpoint, thus, it was no problem.
> But in reality, port : endpoint = 1 : N, thus, counting endpoint
> is BUG, it should count "port".
> This patch fixup it.
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---
>  sound/soc/generic/simple-card-utils.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
> index c69ce1e..119f831 100644
> --- a/sound/soc/generic/simple-card-utils.c
> +++ b/sound/soc/generic/simple-card-utils.c
> @@ -270,7 +270,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
>  static int asoc_simple_card_get_dai_id(struct device_node *ep)
>  {
>         struct device_node *node;
> -       struct device_node *endpoint;
> +       struct device_node *p;
> +       struct device_node *port;
>         int i, id;
>         int ret;
>
> @@ -279,20 +280,22 @@ static int asoc_simple_card_get_dai_id(struct device_node *ep)
>                 return ret;
>
>         node = of_graph_get_port_parent(ep);
> +       port = of_graph_get_port(ep);
>
>         /*
> -        * Non HDMI sound case, counting port/endpoint on its DT
> +        * Non HDMI sound case, counting port on its DT
>          * is enough. Let's count it.
>          */
>         i = 0;
>         id = -1;
> -       for_each_endpoint_of_node(node, endpoint) {
> -               if (endpoint == ep)
> +       for_each_port_of_node(node, p) {
> +               if (port == p)
>                         id = i;
>                 i++;
>         }

This is fragile because it assumes 0-N port numbering. While that's
usually true, it's not guaranteed.

Just add a of_graph_get_port_id() that reads and returns 'reg' value
or 0 if no 'reg'. Or just use of_graph_parse_endpoint().

Rob
Kuninori Morimoto Nov. 30, 2018, 12:47 a.m. UTC | #4
Hi Rob

> > -       for_each_endpoint_of_node(node, endpoint) {
> > -               if (endpoint == ep)
> > +       for_each_port_of_node(node, p) {
> > +               if (port == p)
> >                         id = i;
> >                 i++;
> >         }
> 
> This is fragile because it assumes 0-N port numbering. While that's
> usually true, it's not guaranteed.
> 
> Just add a of_graph_get_port_id() that reads and returns 'reg' value
> or 0 if no 'reg'. Or just use of_graph_parse_endpoint().

OK, will think about this.
How about [1/2] patch ? Is it good or not ?

Best regards
---
Kuninori Morimoto
Kuninori Morimoto Nov. 30, 2018, 1:55 a.m. UTC | #5
Hi Rob, again

> > > -       for_each_endpoint_of_node(node, endpoint) {
> > > -               if (endpoint == ep)
> > > +       for_each_port_of_node(node, p) {
> > > +               if (port == p)
> > >                         id = i;
> > >                 i++;
> > >         }
> > 
> > This is fragile because it assumes 0-N port numbering. While that's
> > usually true, it's not guaranteed.
> > 
> > Just add a of_graph_get_port_id() that reads and returns 'reg' value
> > or 0 if no 'reg'. Or just use of_graph_parse_endpoint().
> 
> OK, will think about this.
> How about [1/2] patch ? Is it good or not ?

Thank you for your advice.
of_graph_parse_endpoint() was good enough !

Best regards
---
Kuninori Morimoto
diff mbox series

Patch

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 3db01ee..2ec4c95 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -585,6 +585,43 @@  struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
 EXPORT_SYMBOL(of_graph_get_port_by_id);
 
 /**
+ * of_graph_get_next_port() - get next port node
+ * @parent: pointer to the parent device node
+ * @prev: previous port node, or NULL to get first
+ *
+ * Return: An 'port' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_port(const struct device_node *parent,
+					   struct device_node *prev)
+{
+	struct device_node *port;
+
+	if (!parent)
+		return NULL;
+
+	if (!prev) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(parent, "ports");
+		if (node)
+			parent = node;
+		port = NULL;
+	} else {
+		port = prev;
+	}
+
+	do {
+		port = of_get_next_child(parent, port);
+		if (!port)
+			return NULL;
+	} while (of_node_cmp(port->name, "port"));
+
+	return port;
+}
+EXPORT_SYMBOL(of_graph_get_next_port);
+
+/**
  * of_graph_get_next_endpoint() - get next endpoint node
  * @parent: pointer to the parent device node
  * @prev: previous endpoint node, or NULL to get first
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index 7fbbf80..d219cc7 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -27,6 +27,17 @@  struct of_endpoint {
 };
 
 /**
+ * for_each_port_of_node - iterate over every port in a device node
+ * @parent: parent device node containing ports
+ * @child: loop variable pointing to the current port node
+ *
+ * When breaking out of the loop, of_node_put(child) has to be called manually.
+ */
+#define for_each_port_of_node(parent, child) \
+	for (child = of_graph_get_next_port(parent, NULL); child != NULL; \
+	     child = of_graph_get_next_port(parent, child))
+
+/**
  * for_each_endpoint_of_node - iterate over every endpoint in a device node
  * @parent: parent device node containing ports and endpoints
  * @child: loop variable pointing to the current endpoint node
@@ -44,6 +55,8 @@  int of_graph_parse_endpoint(const struct device_node *node,
 				struct of_endpoint *endpoint);
 int of_graph_get_endpoint_count(const struct device_node *np);
 struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
+struct device_node *of_graph_get_next_port(const struct device_node *parent,
+					       struct device_node *previous);
 struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
 					struct device_node *previous);
 struct device_node *of_graph_get_endpoint_by_regs(
@@ -75,6 +88,13 @@  static inline struct device_node *of_graph_get_port_by_id(
 	return NULL;
 }
 
+static inline struct device_node *of_graph_get_next_port(
+					const struct device_node *parent,
+					struct device_node *previous)
+{
+	return NULL;
+}
+
 static inline struct device_node *of_graph_get_next_endpoint(
 					const struct device_node *parent,
 					struct device_node *previous)