Hi Rob, Saravana, Tomi, Laurent, Sakari
This is v3 patch-set
I have been posting to add new port base for loop function
as below steps.
[o] done
[@] this patch set
[o] tidyup of_graph_get_endpoint_count()
[o] replace endpoint func - use endpoint_by_regs()
[o] replace endpoint func - use for_each()
[@] add new port function
Current Of-graph has "endpoint base" for loop, but doesn't have
"port base" loop. "endpoint base" loop only is not enough.
This patch-set add new "port base" for loop, and use it.
v2 -> v3
- return NULL if it it doesn't have ports / port
- add visible comment on of_graph_get_next_ports()
v1 -> v2
- add each Reviewed-by / Acked-by
- tidyup/update Kernel Docs
- use prev as parameter
- update git-log explanation
- remove extra changes
Kuninori Morimoto (9):
of: property: add of_graph_get_next_port()
of: property: add of_graph_get_next_port_endpoint()
ASoC: test-component: use new of_graph functions
ASoC: rcar_snd: use new of_graph functions
ASoC: audio-graph-card: use new of_graph functions
ASoC: audio-graph-card2: use new of_graph functions
gpu: drm: omapdrm: use new of_graph functions
fbdev: omapfb: use new of_graph functions
media: xilinx-tpg: use new of_graph functions
drivers/gpu/drm/omapdrm/dss/dpi.c | 3 +-
drivers/gpu/drm/omapdrm/dss/sdi.c | 3 +-
drivers/media/platform/xilinx/xilinx-tpg.c | 3 +-
drivers/of/property.c | 134 ++++++++++++++++++
drivers/video/fbdev/omap2/omapfb/dss/dpi.c | 3 +-
drivers/video/fbdev/omap2/omapfb/dss/dss-of.c | 66 ---------
drivers/video/fbdev/omap2/omapfb/dss/dss.c | 9 +-
drivers/video/fbdev/omap2/omapfb/dss/sdi.c | 3 +-
include/linux/of_graph.h | 66 +++++++++
include/video/omapfb_dss.h | 8 --
sound/soc/generic/audio-graph-card.c | 5 +-
sound/soc/generic/audio-graph-card2.c | 111 +++++++--------
sound/soc/generic/test-component.c | 4 +-
sound/soc/sh/rcar/core.c | 12 +-
14 files changed, 270 insertions(+), 160 deletions(-)
--
2.43.0
We have endpoint base functions
- of_graph_get_next_device_endpoint()
- of_graph_get_device_endpoint_count()
- for_each_of_graph_device_endpoint()
Here, for_each_of_graph_device_endpoint() loop finds each endpoints
ports {
port@0 {
(1) endpoint {...};
};
port@1 {
(2) endpoint {...};
};
...
};
In above case, it finds endpoint as (1) -> (2) -> ...
Basically, user/driver knows which port is used for what, but not in
all cases. For example on flexible/generic driver case, how many ports
are used is not fixed.
For example Sound Generic Card driver which is used from many venders
can't know how many ports are used. Because the driver is very
flexible/generic, it is impossible to know how many ports are used,
it depends on each vender SoC and/or its used board.
And more, the port can have multi endpoints. For example Generic Sound
Card case, it supports many type of connection between CPU / Codec, and
some of them uses multi endpoint in one port.
Then, Generic Sound Card want to handle each connection via "port"
instead of "endpoint".
But, it is very difficult to handle each "port" via
for_each_of_graph_device_endpoint(). Getting "port" by using
of_get_parent() from "endpoint" doesn't work. see below.
ports {
port@0 {
(1) endpoint@0 {...};
(2) endpoint@1 {...};
};
port@1 {
(3) endpoint {...};
};
...
};
In the same time, same reason, we want to handle "ports" same as "port".
node {
=> ports@0 {
port@0 {
endpoint@0 {...};
endpoint@1 {...};
...
};
port@1 {
endpoint@0 {...};
endpoint@1 {...};
...
};
...
};
=> ports@1 {
...
};
};
Add "ports" / "port" base functions.
For above case, we can use
for_each_of_graph_ports(node, ports) {
for_each_of_graph_port(ports, port) {
...
}
}
This loop works both "node" have / doesn't have "ports", like below
node {
port { };
};
node {
ports {
port { };
};
};
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
drivers/of/property.c | 112 +++++++++++++++++++++++++++++++++++++++
include/linux/of_graph.h | 46 ++++++++++++++++
2 files changed, 158 insertions(+)
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
(X) node {
(Y) ports {
(P0) port@0 { endpoint { remote-endpoint = ...; };};
(P10) port@1 { endpoint { remote-endpoint = ...; };
(P11) endpoint { remote-endpoint = ...; };};
(P2) port@2 { endpoint { remote-endpoint = ...; };};
};
};
For example, if I want to handle port@1's 2 endpoints (= P10, P11),
I want to use like below
P10 = of_graph_get_next_endpoint(port1, NULL);
P11 = of_graph_get_next_endpoint(port1, P10);
But 1st one will be error, because of_graph_get_next_endpoint()
requested "parent" means "node" (X) or "ports" (Y), not "port".
Below works, but it will get P0
/* These will be node/ports/port@0/endpoint */
P0 = of_graph_get_next_endpoint(node, NULL);
P0 = of_graph_get_next_endpoint(ports, NULL);
In other words, we can't handle P10/P11 directly via
of_graph_get_next_endpoint() so far.
There is another non intuitive behavior on of_graph_get_next_endpoint().
In case of if I could get P10 pointer for some way, and if I want to
handle port@1 things, I would like use it like below
/*
* "ep" is now P10, and handle port1 things here,
* but we don't know how many endpoints port1 has.
*
* Because "ep" is non NULL now, we can use port1
* as of_graph_get_next_endpoint(port1, xxx)
*/
do {
/* do something for port1 specific things here */
} while (ep = of_graph_get_next_endpoint(port1, ep))
But it also not worked as I expected.
I expect it will be P10 -> P11 -> NULL,
but it will be P10 -> P11 -> P2, because
of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port".
It is not useful on generic driver.
It uses of_get_next_child() instead for now, but it is not intuitive.
And it doesn't check node name (= "endpoint").
To handle endpoint more intuitive, create of_graph_get_next_port_endpoint()
of_graph_get_next_port_endpoint(port1, NULL); // P10
of_graph_get_next_port_endpoint(port1, P10); // P11
of_graph_get_next_port_endpoint(port1, P11); // NULL
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
drivers/of/property.c | 22 ++++++++++++++++++++++
include/linux/of_graph.h | 20 ++++++++++++++++++++
2 files changed, 42 insertions(+)
Current test-component.c is using for_each_endpoint_of_node()
for parsing "port", because there was no "port" base loop before.
It has been assuming 1 port has 1 endpoint here.
But now we can use "port" base loop (= for_each_of_graph_port()).
Let's replace for_each function from "endpoint" base to "port" base.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Mark Brown <broonie@kernel.org>
---
sound/soc/generic/test-component.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sh/rcar/core.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Mark Brown <broonie@kernel.org>
---
sound/soc/generic/audio-graph-card.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
@@ -374,10 +374,7 @@ static int __graph_for_each_link(struct simple_util_priv *priv,cpu_ep=NULL;/* loop for all CPU endpoint */-while(1){-cpu_ep=of_get_next_child(cpu_port,cpu_ep);-if(!cpu_ep)-break;+for_each_of_graph_port_endpoint(cpu_port,cpu_ep){/* get codec */codec_ep=of_graph_get_remote_endpoint(cpu_ep);
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Mark Brown <broonie@kernel.org>
---
sound/soc/generic/audio-graph-card2.c | 111 ++++++++++++--------------
1 file changed, 49 insertions(+), 62 deletions(-)
@@ -530,67 +523,70 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,*};*};*/-structdevice_node*mcpu_ep=port_to_endpoint(mcpu_port);-structdevice_node*mcpu_ep_n=mcpu_ep;-structdevice_node*mcpu_port_top=of_get_next_child(port_to_ports(mcpu_port),NULL);-structdevice_node*mcpu_ep_top=port_to_endpoint(mcpu_port_top);+structdevice_node*mcpu_ep_n;+structdevice_node*mcpu_ep=of_graph_get_next_port_endpoint(mcpu_port,NULL);+structdevice_node*mcpu_ports=port_to_ports(mcpu_port);+structdevice_node*mcpu_port_top=of_graph_get_next_port(mcpu_ports,NULL);+structdevice_node*mcpu_ep_top=of_graph_get_next_port_endpoint(mcpu_port_top,NULL);structdevice_node*mcodec_ep_top=of_graph_get_remote_endpoint(mcpu_ep_top);structdevice_node*mcodec_port_top=ep_to_port(mcodec_ep_top);structdevice_node*mcodec_ports=port_to_ports(mcodec_port_top);intnm_max=max(dai_link->num_cpus,dai_link->num_codecs);-intret=-EINVAL;+intret=0;-if(cpu_idx>dai_link->num_cpus)+if(cpu_idx>dai_link->num_cpus){+ret=-EINVAL;gotomcpu_err;+}-while(1){+for_each_of_graph_port_endpoint(mcpu_port,mcpu_ep_n){structdevice_node*mcodec_ep_n;structdevice_node*mcodec_port_i;structdevice_node*mcodec_port;intcodec_idx;-if(*nm_idx>nm_max)-break;+/* ignore 1st ep which is for element */+if(mcpu_ep_n==mcpu_ep)+continue;-mcpu_ep_n=of_get_next_child(mcpu_port,mcpu_ep_n);-if(!mcpu_ep_n){-ret=0;+if(*nm_idx>nm_max)break;-}mcodec_ep_n=of_graph_get_remote_endpoint(mcpu_ep_n);mcodec_port=ep_to_port(mcodec_ep_n);-if(mcodec_ports!=port_to_ports(mcodec_port))+if(mcodec_ports!=port_to_ports(mcodec_port)){+ret=-EINVAL;gotomcpu_err;+}codec_idx=0;-mcodec_port_i=of_get_next_child(mcodec_ports,NULL);-while(1){-if(codec_idx>dai_link->num_codecs)-gotomcodec_err;--mcodec_port_i=of_get_next_child(mcodec_ports,mcodec_port_i);+ret=-EINVAL;+for_each_of_graph_port(mcodec_ports,mcodec_port_i){-if(!mcodec_port_i)-gotomcodec_err;+/* ignore 1st port which is for pair connection */+if(mcodec_port_top==mcodec_port_i)+continue;-if(mcodec_port_i==mcodec_port)+if(codec_idx>dai_link->num_codecs)break;+if(mcodec_port_i==mcodec_port){+dai_link->ch_maps[*nm_idx].cpu=cpu_idx;+dai_link->ch_maps[*nm_idx].codec=codec_idx;++(*nm_idx)++;+ret=0;+break;+}codec_idx++;}--dai_link->ch_maps[*nm_idx].cpu=cpu_idx;-dai_link->ch_maps[*nm_idx].codec=codec_idx;--(*nm_idx)++;-of_node_put(mcodec_port_i);-mcodec_err:of_node_put(mcodec_port);of_node_put(mcpu_ep_n);of_node_put(mcodec_ep_n);+if(ret<0)+break;}mcpu_err:of_node_put(mcpu_ep);
@@ -674,7 +670,7 @@ static int graph_parse_node_single(struct simple_util_priv *priv,structdevice_node*port,structlink_info*li,intis_cpu){-structdevice_node*ep=port_to_endpoint(port);+structdevice_node*ep=of_graph_get_next_port_endpoint(port,NULL);intret=__graph_parse_node(priv,gtype,ep,li,is_cpu,0);of_node_put(ep);
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
drivers/gpu/drm/omapdrm/dss/dpi.c | 3 ++-
drivers/gpu/drm/omapdrm/dss/sdi.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
drivers/video/fbdev/omap2/omapfb/dss/dpi.c | 3 +-
drivers/video/fbdev/omap2/omapfb/dss/dss-of.c | 66 -------------------
drivers/video/fbdev/omap2/omapfb/dss/dss.c | 9 +--
drivers/video/fbdev/omap2/omapfb/dss/sdi.c | 3 +-
include/video/omapfb_dss.h | 8 ---
5 files changed, 9 insertions(+), 80 deletions(-)
Now we can use new port related functions for port parsing. Use it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
drivers/media/platform/xilinx/xilinx-tpg.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: Rob Herring <robh@kernel.org> Date: 2024-08-26 15:40:12
On Mon, Aug 26, 2024 at 02:43:28AM +0000, Kuninori Morimoto wrote:
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
quoted hunk
(X) node {
(Y) ports {
(P0) port@0 { endpoint { remote-endpoint = ...; };};
(P10) port@1 { endpoint { remote-endpoint = ...; };
(P11) endpoint { remote-endpoint = ...; };};
(P2) port@2 { endpoint { remote-endpoint = ...; };};
};
};
For example, if I want to handle port@1's 2 endpoints (= P10, P11),
I want to use like below
P10 = of_graph_get_next_endpoint(port1, NULL);
P11 = of_graph_get_next_endpoint(port1, P10);
But 1st one will be error, because of_graph_get_next_endpoint()
requested "parent" means "node" (X) or "ports" (Y), not "port".
Below works, but it will get P0
/* These will be node/ports/port@0/endpoint */
P0 = of_graph_get_next_endpoint(node, NULL);
P0 = of_graph_get_next_endpoint(ports, NULL);
In other words, we can't handle P10/P11 directly via
of_graph_get_next_endpoint() so far.
There is another non intuitive behavior on of_graph_get_next_endpoint().
In case of if I could get P10 pointer for some way, and if I want to
handle port@1 things, I would like use it like below
/*
* "ep" is now P10, and handle port1 things here,
* but we don't know how many endpoints port1 has.
*
* Because "ep" is non NULL now, we can use port1
* as of_graph_get_next_endpoint(port1, xxx)
*/
do {
/* do something for port1 specific things here */
} while (ep = of_graph_get_next_endpoint(port1, ep))
But it also not worked as I expected.
I expect it will be P10 -> P11 -> NULL,
but it will be P10 -> P11 -> P2, because
of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port".
It is not useful on generic driver.
It uses of_get_next_child() instead for now, but it is not intuitive.
And it doesn't check node name (= "endpoint").
To handle endpoint more intuitive, create of_graph_get_next_port_endpoint()
of_graph_get_next_port_endpoint(port1, NULL); // P10
of_graph_get_next_port_endpoint(port1, P10); // P11
of_graph_get_next_port_endpoint(port1, P11); // NULL
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
drivers/of/property.c | 22 ++++++++++++++++++++++
include/linux/of_graph.h | 20 ++++++++++++++++++++
2 files changed, 42 insertions(+)
Really, this check is validation as no other name is valid in a
port node. The kernel is not responsible for validation, but okay.
However, if we are going to keep this, might as well make it WARN().
quoted hunk
+
+ return prev;
+}
+EXPORT_SYMBOL(of_graph_get_next_port_endpoint);
+
/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
Hmm...
of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port",
but new helper doesn't have such feature.
Even though I try to replace it with new helper, I guess it will be
almost same as current of_graph_get_next_endpoint() anyway.
Alternative idea is...
One of the big user of of_graph_get_next_endpoint() is
for_each_endpoint_of_node() loop.
So we can replace it to..
- for_each_endpoint_of_node(parent, endpoint) {
+ for_each_of_graph_port(parent, port) {
+ for_each_of_graph_port_endpoint(port, endpoint) {
Above is possible, but it replaces single loop to multi loops.
And, we still need to consider about of_fwnode_graph_get_next_endpoint()
which is the last user of of_graph_get_next_endpoint()
quoted
+struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
+ struct device_node *prev)
+{
+ do {
+ prev = of_get_next_child(port, prev);
+ if (!prev)
+ break;
+ } while (!of_node_name_eq(prev, "endpoint"));
Really, this check is validation as no other name is valid in a
port node. The kernel is not responsible for validation, but okay.
However, if we are going to keep this, might as well make it WARN().
OK, will do in v4
quoted
+/**
+ * for_each_of_graph_port_endpoint - iterate over every endpoint in a port node
+ * @parent: parent port node
+ * @child: loop variable pointing to the current endpoint node
+ *
+ * When breaking out of the loop, of_node_put(child) has to be called manually.
No need for this requirement anymore. Use cleanup.h so this is
automatic.
Do you mean it should include __free() inside this loop, like _scoped() ?
#define for_each_child_of_node_scoped(parent, child) \
for (struct device_node *child __free(device_node) = \
of_get_next_child(parent, NULL); \
child != NULL; \
child = of_get_next_child(parent, child))
In such case, I wonder does it need to have _scoped() in loop name ?
And in such case, I think we want to have non _scoped() loop too ?
For example, when user want to use the param.
for_each_of_graph_port_endpoint(port, endpoint)
if (xxx == yyy)
return endpoint;
for_each_of_graph_port_endpoint_scoped(port, endpoint)
if (xxx == yyy)
return of_node_get(endpoint)
Thank you for your help !!
Best regards
---
Kuninori Morimoto
From: Sakari Ailus <sakari.ailus@iki.fi> Date: 2024-08-27 10:41:43
Rob, Kunimori-san,
On Mon, Aug 26, 2024 at 10:40:09AM -0500, Rob Herring wrote:
On Mon, Aug 26, 2024 at 02:43:28AM +0000, Kuninori Morimoto wrote:
quoted
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
The fwnode graph API has fwnode_graph_get_endpoint_by_id() which can also
be used to obtain endpoints within a port. It does the same than
of_graph_get_endpoint_by_regs() with the addition that it also has a
flags field to allow e.g. returning endpoints with regs higher than
requested (FWNODE_GRAPH_ENDPOINT_NEXT).
Most users dealing with endpoints on fwnode property API use this, could
something like this be done on OF as well? Probably a similar flag would be
needed though.
--
Kind regards,
Sakari Ailus
From: Rob Herring <robh@kernel.org> Date: 2024-08-27 13:55:06
+Jonathan C for the naming
On Mon, Aug 26, 2024 at 7:14 PM Kuninori Morimoto
[off-list ref] wrote:
Hi Rob
quoted
quoted
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
Hmm...
of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port",
but new helper doesn't have such feature.
Right, but the "feature" is somewhat awkward as you said. You
generally should know what port you are operating on.
Even though I try to replace it with new helper, I guess it will be
almost same as current of_graph_get_next_endpoint() anyway.
Alternative idea is...
One of the big user of of_graph_get_next_endpoint() is
for_each_endpoint_of_node() loop.
So we can replace it to..
- for_each_endpoint_of_node(parent, endpoint) {
+ for_each_of_graph_port(parent, port) {
+ for_each_of_graph_port_endpoint(port, endpoint) {
Above is possible, but it replaces single loop to multi loops.
And, we still need to consider about of_fwnode_graph_get_next_endpoint()
which is the last user of of_graph_get_next_endpoint()
I missed fwnode_graph_get_next_endpoint() which has lots of users.
Though almost all of those are just "get the endpoint" and assume
there is only 1. In any case, it's a lot more than 3, so nevermind for
now.
quoted
quoted
+struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
+ struct device_node *prev)
+{
+ do {
+ prev = of_get_next_child(port, prev);
+ if (!prev)
+ break;
+ } while (!of_node_name_eq(prev, "endpoint"));
Really, this check is validation as no other name is valid in a
port node. The kernel is not responsible for validation, but okay.
However, if we are going to keep this, might as well make it WARN().
OK, will do in v4
quoted
quoted
+/**
+ * for_each_of_graph_port_endpoint - iterate over every endpoint in a port node
+ * @parent: parent port node
+ * @child: loop variable pointing to the current endpoint node
+ *
+ * When breaking out of the loop, of_node_put(child) has to be called manually.
No need for this requirement anymore. Use cleanup.h so this is
automatic.
Do you mean it should include __free() inside this loop, like _scoped() ?
Yes.
#define for_each_child_of_node_scoped(parent, child) \
for (struct device_node *child __free(device_node) = \
of_get_next_child(parent, NULL); \
child != NULL; \
child = of_get_next_child(parent, child))
In such case, I wonder does it need to have _scoped() in loop name ?
Well, we added that to avoid changing all the users at once.
And in such case, I think we want to have non _scoped() loop too ?
Do we have a user? I don't think we need it because anywhere we need
the node iterator pointer outside the loop that can be done explicitly
(no_free_ptr()).
So back to the name, I don't think we need _scoped in it. I think if
any user treats the iterator like it's the old style, the compiler is
going to complain.
For example, when user want to use the param.
for_each_of_graph_port_endpoint(port, endpoint)
if (xxx == yyy)
return endpoint;
for_each_of_graph_port_endpoint_scoped(port, endpoint)
if (xxx == yyy)
return of_node_get(endpoint)
Actually, you would do "return_ptr(endpoint)" here.
Rob
From: Rob Herring <robh@kernel.org> Date: 2024-08-27 14:05:17
On Tue, Aug 27, 2024 at 5:47 AM Sakari Ailus [off-list ref] wrote:
Rob, Kunimori-san,
On Mon, Aug 26, 2024 at 10:40:09AM -0500, Rob Herring wrote:
quoted
On Mon, Aug 26, 2024 at 02:43:28AM +0000, Kuninori Morimoto wrote:
quoted
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
The fwnode graph API has fwnode_graph_get_endpoint_by_id() which can also
be used to obtain endpoints within a port. It does the same than
of_graph_get_endpoint_by_regs() with the addition that it also has a
flags field to allow e.g. returning endpoints with regs higher than
requested (FWNODE_GRAPH_ENDPOINT_NEXT).
Looks to me like FWNODE_GRAPH_ENDPOINT_NEXT is always used with
endpoint #0. That's equivalent to passing -1 for the endpoint number
with the OF API.
Most users dealing with endpoints on fwnode property API use this, could
something like this be done on OF as well? Probably a similar flag would be
needed though.
I had fixed almost all the OF cases at one point. Unfortunately, there
were a few corner cases that I didn't address to eliminate the API. So
now it has proliferated with the fwnode API.
Rob
From: Sakari Ailus <sakari.ailus@iki.fi> Date: 2024-08-27 14:15:56
Hi Rob,
On Tue, Aug 27, 2024 at 09:05:02AM -0500, Rob Herring wrote:
On Tue, Aug 27, 2024 at 5:47 AM Sakari Ailus [off-list ref] wrote:
quoted
Rob, Kunimori-san,
On Mon, Aug 26, 2024 at 10:40:09AM -0500, Rob Herring wrote:
quoted
On Mon, Aug 26, 2024 at 02:43:28AM +0000, Kuninori Morimoto wrote:
quoted
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
The fwnode graph API has fwnode_graph_get_endpoint_by_id() which can also
be used to obtain endpoints within a port. It does the same than
of_graph_get_endpoint_by_regs() with the addition that it also has a
flags field to allow e.g. returning endpoints with regs higher than
requested (FWNODE_GRAPH_ENDPOINT_NEXT).
Looks to me like FWNODE_GRAPH_ENDPOINT_NEXT is always used with
endpoint #0. That's equivalent to passing -1 for the endpoint number
with the OF API.
If the caller needs a single endpoint only, then the two are the same, yes.
The NEXT flag can still be used for obtaining further endpoints, unlike
setting endpoint to -1 in of_graph_get_endpoint_by_regs().
quoted
Most users dealing with endpoints on fwnode property API use this, could
something like this be done on OF as well? Probably a similar flag would be
needed though.
I had fixed almost all the OF cases at one point. Unfortunately, there
were a few corner cases that I didn't address to eliminate the API. So
now it has proliferated with the fwnode API.
Much of the usage of fwnode_graph_get_next_endpoint() is conversion from
the OF API but there are some newer drivers, too. I admit I've sometimes
missed this in review. At the same time I can say most users in the media
tree do employ fwnode_graph_get_endpoint_by_id() already.
The good thing is that almost all current users are camera sensors and
converting them is fairly trivial. I can post patches but it'll take a
while...
--
Kind regards,
Sakari Ailus
And, we still need to consider about of_fwnode_graph_get_next_endpoint()
which is the last user of of_graph_get_next_endpoint()
I missed fwnode_graph_get_next_endpoint() which has lots of users.
Though almost all of those are just "get the endpoint" and assume
there is only 1. In any case, it's a lot more than 3, so nevermind for
now.
OK, thanks.
So back to the name, I don't think we need _scoped in it. I think if
any user treats the iterator like it's the old style, the compiler is
going to complain.
quoted
For example, when user want to use the param.
for_each_of_graph_port_endpoint(port, endpoint)
if (xxx == yyy)
return endpoint;
for_each_of_graph_port_endpoint_scoped(port, endpoint)
if (xxx == yyy)
return of_node_get(endpoint)
Actually, you would do "return_ptr(endpoint)" here.
OK, nice to know about this
I will try to use this style on v4
Thank you for your help !!
Best regards
---
Kuninori Morimoto
From: Jonathan Cameron <jic23@kernel.org> Date: 2024-08-31 10:24:53
On Tue, 27 Aug 2024 08:54:51 -0500
Rob Herring [off-list ref] wrote:
+Jonathan C for the naming
On Mon, Aug 26, 2024 at 7:14 PM Kuninori Morimoto
[off-list ref] wrote:
quoted
Hi Rob
quoted
quoted
We already have of_graph_get_next_endpoint(), but it is not
intuitive to use in some case.
Can of_graph_get_next_endpoint() users be replaced with your new
helpers? I'd really like to get rid of the 3 remaining users.
Hmm...
of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port",
but new helper doesn't have such feature.
Right, but the "feature" is somewhat awkward as you said. You
generally should know what port you are operating on.
quoted
Even though I try to replace it with new helper, I guess it will be
almost same as current of_graph_get_next_endpoint() anyway.
Alternative idea is...
One of the big user of of_graph_get_next_endpoint() is
for_each_endpoint_of_node() loop.
So we can replace it to..
- for_each_endpoint_of_node(parent, endpoint) {
+ for_each_of_graph_port(parent, port) {
+ for_each_of_graph_port_endpoint(port, endpoint) {
Above is possible, but it replaces single loop to multi loops.
And, we still need to consider about of_fwnode_graph_get_next_endpoint()
which is the last user of of_graph_get_next_endpoint()
I missed fwnode_graph_get_next_endpoint() which has lots of users.
Though almost all of those are just "get the endpoint" and assume
there is only 1. In any case, it's a lot more than 3, so nevermind for
now.
quoted
quoted
quoted
+struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
+ struct device_node *prev)
+{
+ do {
+ prev = of_get_next_child(port, prev);
+ if (!prev)
+ break;
+ } while (!of_node_name_eq(prev, "endpoint"));
Really, this check is validation as no other name is valid in a
port node. The kernel is not responsible for validation, but okay.
However, if we are going to keep this, might as well make it WARN().
OK, will do in v4
quoted
quoted
+/**
+ * for_each_of_graph_port_endpoint - iterate over every endpoint in a port node
+ * @parent: parent port node
+ * @child: loop variable pointing to the current endpoint node
+ *
+ * When breaking out of the loop, of_node_put(child) has to be called manually.
No need for this requirement anymore. Use cleanup.h so this is
automatic.
Do you mean it should include __free() inside this loop, like _scoped() ?
Yes.
quoted
#define for_each_child_of_node_scoped(parent, child) \
for (struct device_node *child __free(device_node) = \
of_get_next_child(parent, NULL); \
child != NULL; \
child = of_get_next_child(parent, child))
In such case, I wonder does it need to have _scoped() in loop name ?
Well, we added that to avoid changing all the users at once.
quoted
And in such case, I think we want to have non _scoped() loop too ?
Do we have a user? I don't think we need it because anywhere we need
the node iterator pointer outside the loop that can be done explicitly
(no_free_ptr()).
So back to the name, I don't think we need _scoped in it. I think if
any user treats the iterator like it's the old style, the compiler is
going to complain.
Hmm. Up to you but I'd be concerned that the scoping stuff is non
obvious enough that it is worth making people really really aware
it is going on.
However I don't feel strongly about it.
For the other _scoped iterators there is some push back
on the churn using them is causing so I doubt we'll ever get rid
of the non scoped variants. For something new that's not a concern.
Jonathan
quoted
For example, when user want to use the param.
for_each_of_graph_port_endpoint(port, endpoint)
if (xxx == yyy)
return endpoint;
for_each_of_graph_port_endpoint_scoped(port, endpoint)
if (xxx == yyy)
return of_node_get(endpoint)
Actually, you would do "return_ptr(endpoint)" here.
Rob
Do you mean it should include __free() inside this loop, like _scoped() ?
(snip)
quoted
quoted
In such case, I wonder does it need to have _scoped() in loop name ?
(snip)
quoted
So back to the name, I don't think we need _scoped in it. I think if
any user treats the iterator like it's the old style, the compiler is
going to complain.
Hmm. Up to you but I'd be concerned that the scoping stuff is non
obvious enough that it is worth making people really really aware
it is going on.
However I don't feel strongly about it.
For the other _scoped iterators there is some push back
on the churn using them is causing so I doubt we'll ever get rid
of the non scoped variants. For something new that's not a concern.
I noticed that we can write below code, and then, and there is no waning/error
from compiler.
Now for_each macro is using __free()
#define for_each_of_graph_port(parent, child) \
for (... *child __free(device_node) = ...)
(A) struct device_node *node = xxx;
for_each_of_graph_port(parent, node) {
(B) /* do something */
}
(C) xxx = node;
In this case, "(A) node" and "(C) node" are same, but "(B) node" are different.
New user might confuse about this behavior.
Thank you for your help !!
Best regards
---
Kuninori Morimoto