Improve remote-endpoint parsing
cover Improve remote-endpoint parsing
Some changes to do a more accurate parsing of remote-endpoints. Making fw_devlink a tiny bit more efficient and the debug logs a bit cleaner when trying to debug fw_devlink.
Saravana Kannan (2):
of: property: Improve finding the consumer of a remote-endpoint
property
of: property: Improve finding the supplier of a remote-endpoint
property
drivers/of/property.c | 71 ++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 38 deletions(-)
Signature · 1 line
2.43.0.594.gd9cf4e227d-goog
PATCH 1/2 of: property: Improve finding the consumer of a remote-endpoint property
We have a more accurate function to find the right consumer of a remote-endpoint property instead of searching for a parent with compatible string property. So, use that instead. While at it, make the code to find the consumer a bit more flexible and based on the property being parsed.
--- drivers/of/property.c | 52 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 37 deletions(-)
drivers/of/property.c +15 -37
@@ -1063,36 +1063,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,return of_device_get_match_data (dev); } -static struct device_node *of_get_compat_node (struct device_node *np) -{ -of_node_get (np); - -while (np) { -if (!of_device_is_available (np)) { -of_node_put (np); - np =NULL ; - } - -if (of_property_present (np,"compatible" )) -break ; - - np =of_get_next_parent (np); - } - -return np; -} - -static struct device_node *of_get_compat_node_parent (struct device_node *np) -{ -struct device_node *parent, *node; - - parent =of_get_parent (np); - node =of_get_compat_node (parent); -of_node_put (parent); - -return node; -} -static void of_link_to_phandle (struct device_node *con_np,struct device_node *sup_np) {
@@ -1222,10 +1192,10 @@ static struct device_node *parse_##fname(struct device_node *np, \* parse_prop.prop_name: Name of property holding a phandle value * parse_prop.index: For properties holding a list of phandles, this is the * index into the list +* @get_con_dev: If the consumer node containing the property is never converted +* to a struct device, implement this ops so fw_devlink can use it +* to find the true consumer. * @optional: Describes whether a supplier is mandatory or not -* @node_not_dev: The consumer node containing the property is never converted -* to a struct device. Instead, parse ancestor nodes for the -* compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are
@@ -1236,8 +1206,8 @@ static struct device_node *parse_##fname(struct device_node *np, \struct supplier_bindings {struct device_node *(*parse_prop)(struct device_node *np,const char *prop_name,int index); +struct device_node *(*get_con_dev)(struct device_node *np);bool optional; -bool node_not_dev; };DEFINE_SIMPLE_PROP (clocks,"clocks" ,"#clock-cells" )
@@ -1328,6 +1298,11 @@ static struct device_node *parse_interrupts(struct device_node *np,return of_irq_parse_one (np, index, &sup_args) ?NULL : sup_args.np; } +static struct device_node *get_remote_endpoint_dev (struct device_node *np) +{ +return to_of_node (fwnode_graph_get_port_parent (of_fwnode_handle (np))); +} +static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_clocks, }, { .parse_prop = parse_interconnects, },
@@ -1352,7 +1327,10 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_pinctrl6, }, { .parse_prop = parse_pinctrl7, }, { .parse_prop = parse_pinctrl8, }, - { .parse_prop = parse_remote_endpoint, .node_not_dev = true, }, + { + .parse_prop = parse_remote_endpoint, + .get_con_dev = get_remote_endpoint_dev, + }, { .parse_prop = parse_pwms, }, { .parse_prop = parse_resets, }, { .parse_prop = parse_leds, },
@@ -1403,8 +1381,8 @@ static int of_link_property(struct device_node *con_np, const char *prop_name)while ((phandle = s->parse_prop (con_np, prop_name, i))) {struct device_node *con_dev_np; - con_dev_np = s->node_not_dev - ?of_get_compat_node_parent (con_np) + con_dev_np = s->get_con_dev + ? s->get_con_dev (con_np) :of_node_get (con_np); matched = true; i++;
Signature · 1 line
2.43.0.594.gd9cf4e227d-goog
Rob Herring
maintainerRe: [PATCH v1 1/2] of: property: Improve finding the consumer of a remote-endpoint property
Quoted 78 lines · Saravana Kannan
We have a more accurate function to find the right consumer of a remote-endpoint property instead of searching for a parent with compatible string property. So, use that instead. While at it, make the code to find the consumer a bit more flexible and based on the property being parsed.
Fixes f7514a663016 ("of: property: fw_devlink: Add support for remote-endpoint")Signed-off-by Saravana Kannan <[email protected]>--- drivers/of/property.c | 52 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 37 deletions(-)drivers/of/property.c +4
-34@@ -1063,36 +1063,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,return of_device_get_match_data (dev); } -static struct device_node *of_get_compat_node (struct device_node *np) -{ -of_node_get (np); - -while (np) { -if (!of_device_is_available (np)) { -of_node_put (np); - np =NULL ; - } - -if (of_property_present (np,"compatible" )) -break ; - - np =of_get_next_parent (np); - } - -return np; -} - -static struct device_node *of_get_compat_node_parent (struct device_node *np) -{ -struct device_node *parent, *node; - - parent =of_get_parent (np); - node =of_get_compat_node (parent); -of_node_put (parent); - -return node; -} -static void of_link_to_phandle (struct device_node *con_np,struct device_node *sup_np) {@@ -1222,10 +1192,10 @@ static struct device_node *parse_##fname(struct device_node *np, \* parse_prop.prop_name: Name of property holding a phandle value * parse_prop.index: For properties holding a list of phandles, this is the * index into the list +* @get_con_dev: If the consumer node containing the property is never converted +* to a struct device, implement this ops so fw_devlink can use it +* to find the true consumer. * @optional: Describes whether a supplier is mandatory or not -* @node_not_dev: The consumer node containing the property is never converted -* to a struct device. Instead, parse ancestor nodes for the -* compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are @@ -1236,8 +1206,8 @@ static struct device_node *parse_##fname(struct device_node *np, \struct supplier_bindings {struct device_node *(*parse_prop)(struct device_node *np,const char *prop_name,int index); +struct device_node *(*get_con_dev)(struct device_node *np);bool optional; -bool node_not_dev; };DEFINE_SIMPLE_PROP (clocks,"clocks" ,"#clock-cells" )
drivers/of/property.c static struct device_node *parse_interrupts(struct device_node *np, · line 1303
Quoted 6 lines
drivers/of/property.c +3
-0@@ -1328,6 +1298,11 @@ static struct device_node *parse_interrupts(struct device_node *np,return of_irq_parse_one (np, index, &sup_args) ?NULL : sup_args.np; } +static struct device_node *get_remote_endpoint_dev (struct device_node *np) +{ +return to_of_node (fwnode_graph_get_port_parent (of_fwnode_handle (np)));
DT APIs shouldn't depend on fwnode APIs.
Otherwise, this series looks good.
Re: [PATCH v1 1/2] of: property: Improve finding the consumer of a remote-endpoint property
Quoted 83 lines · Rob Herring
Quoted 81 lines · Saravana Kannan
We have a more accurate function to find the right consumer of a remote-endpoint property instead of searching for a parent with compatible string property. So, use that instead. While at it, make the code to find the consumer a bit more flexible and based on the property being parsed.
Fixes f7514a663016 ("of: property: fw_devlink: Add support for remote-endpoint")Signed-off-by Saravana Kannan <[email protected]>--- drivers/of/property.c | 52 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 37 deletions(-)drivers/of/property.c +4
-34@@ -1063,36 +1063,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,return of_device_get_match_data (dev); } -static struct device_node *of_get_compat_node (struct device_node *np) -{ -of_node_get (np); - -while (np) { -if (!of_device_is_available (np)) { -of_node_put (np); - np =NULL ; - } - -if (of_property_present (np,"compatible" )) -break ; - - np =of_get_next_parent (np); - } - -return np; -} - -static struct device_node *of_get_compat_node_parent (struct device_node *np) -{ -struct device_node *parent, *node; - - parent =of_get_parent (np); - node =of_get_compat_node (parent); -of_node_put (parent); - -return node; -} -static void of_link_to_phandle (struct device_node *con_np,struct device_node *sup_np) {@@ -1222,10 +1192,10 @@ static struct device_node *parse_##fname(struct device_node *np, \* parse_prop.prop_name: Name of property holding a phandle value * parse_prop.index: For properties holding a list of phandles, this is the * index into the list +* @get_con_dev: If the consumer node containing the property is never converted +* to a struct device, implement this ops so fw_devlink can use it +* to find the true consumer. * @optional: Describes whether a supplier is mandatory or not -* @node_not_dev: The consumer node containing the property is never converted -* to a struct device. Instead, parse ancestor nodes for the -* compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are @@ -1236,8 +1206,8 @@ static struct device_node *parse_##fname(struct device_node *np, \struct supplier_bindings {struct device_node *(*parse_prop)(struct device_node *np,const char *prop_name,int index); +struct device_node *(*get_con_dev)(struct device_node *np);bool optional; -bool node_not_dev; };DEFINE_SIMPLE_PROP (clocks,"clocks" ,"#clock-cells" )@@ -1328,6 +1298,11 @@ static struct device_node *parse_interrupts(struct device_node *np,return of_irq_parse_one (np, index, &sup_args) ?NULL : sup_args.np; }
Quoted 5 lines
drivers/of/property.c static struct device_node *parse_interrupts(struct device_node *np, · line 1303
Quoted 3 lines
drivers/of/property.c +3
-0+static struct device_node *get_remote_endpoint_dev (struct device_node *np) +{ +return to_of_node (fwnode_graph_get_port_parent (of_fwnode_handle (np)));DT APIs shouldn't depend on fwnode APIs.
I get what you are saying, but is it an API though? It's a static internal function that's eventually used by .add_link to add fwnode links. Would it be better if I rolled this into two separate inline code where this function is getting called from? I'm trying to avoid duplicating the function that's already present in fwnode_graph_get_port_parent(), but it also feels too specific an op to introduce into drivers/of/property.c
How would you like me to handle this? I don't see a good option.
Quoted 1 line
Otherwise, this series looks good.
Thanks,
Saravana
Re: [PATCH v1 1/2] of: property: Improve finding the consumer of a remote-endpoint property
Quoted 99 lines · Saravana Kannan
Quoted 83 lines · Rob Herring
Quoted 81 lines · Saravana Kannan
We have a more accurate function to find the right consumer of a remote-endpoint property instead of searching for a parent with compatible string property. So, use that instead. While at it, make the code to find the consumer a bit more flexible and based on the property being parsed.
Fixes f7514a663016 ("of: property: fw_devlink: Add support for remote-endpoint")Signed-off-by Saravana Kannan <[email protected]>--- drivers/of/property.c | 52 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 37 deletions(-)drivers/of/property.c +4
-34@@ -1063,36 +1063,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,return of_device_get_match_data (dev); } -static struct device_node *of_get_compat_node (struct device_node *np) -{ -of_node_get (np); - -while (np) { -if (!of_device_is_available (np)) { -of_node_put (np); - np =NULL ; - } - -if (of_property_present (np,"compatible" )) -break ; - - np =of_get_next_parent (np); - } - -return np; -} - -static struct device_node *of_get_compat_node_parent (struct device_node *np) -{ -struct device_node *parent, *node; - - parent =of_get_parent (np); - node =of_get_compat_node (parent); -of_node_put (parent); - -return node; -} -static void of_link_to_phandle (struct device_node *con_np,struct device_node *sup_np) {@@ -1222,10 +1192,10 @@ static struct device_node *parse_##fname(struct device_node *np, \* parse_prop.prop_name: Name of property holding a phandle value * parse_prop.index: For properties holding a list of phandles, this is the * index into the list +* @get_con_dev: If the consumer node containing the property is never converted +* to a struct device, implement this ops so fw_devlink can use it +* to find the true consumer. * @optional: Describes whether a supplier is mandatory or not -* @node_not_dev: The consumer node containing the property is never converted -* to a struct device. Instead, parse ancestor nodes for the -* compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are @@ -1236,8 +1206,8 @@ static struct device_node *parse_##fname(struct device_node *np, \struct supplier_bindings {struct device_node *(*parse_prop)(struct device_node *np,const char *prop_name,int index); +struct device_node *(*get_con_dev)(struct device_node *np);bool optional; -bool node_not_dev; };DEFINE_SIMPLE_PROP (clocks,"clocks" ,"#clock-cells" )@@ -1328,6 +1298,11 @@ static struct device_node *parse_interrupts(struct device_node *np,return of_irq_parse_one (np, index, &sup_args) ?NULL : sup_args.np; }Quoted 5 lines
drivers/of/property.c static struct device_node *parse_interrupts(struct device_node *np, · line 1303
Quoted 3 lines
drivers/of/property.c +3
-0+static struct device_node *get_remote_endpoint_dev (struct device_node *np) +{ +return to_of_node (fwnode_graph_get_port_parent (of_fwnode_handle (np)));DT APIs shouldn't depend on fwnode APIs.
I get what you are saying, but is it an API though? It's a static internal function that's eventually used by .add_link to add fwnode links. Would it be better if I rolled this into two separate inline code where this function is getting called from? I'm trying to avoid duplicating the function that's already present in
fwnode_graph_get_port_parent(), but it also feels too specific an op to introduce intodrivers/of/property.c
Quoted 1 line
How would you like me to handle this? I don't see a good option.
Nevermind, there's already of_graph_get_port_parent() that does exactly the same as fwnode_graph_get_port_parent(). I'll just use that.
-Saravana
PATCH 2/2 of: property: Improve finding the supplier of a remote-endpoint property
In reply to Saravana KannanAfter commit 4a032827daa8 ("of: property: Simplify of_link_to_phandle()"), remote-endpoint properties created a fwnode link from the consumer device to the supplier endpoint. This is a tiny bit inefficient (not buggy) when trying to create device links or detecting cycles. So, improve this the same way we improved finding the consumer of a remote-endpoint property.
--- drivers/of/property.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
drivers/of/property.c +18 -1
@@ -1232,7 +1232,6 @@ DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) -DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL) DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells") DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells")DEFINE_SIMPLE_PROP (leds,"leds" ,NULL )
@@ -1303,6 +1302,24 @@ static struct device_node *get_remote_endpoint_dev(struct device_node *np)return to_of_node (fwnode_graph_get_port_parent (of_fwnode_handle (np))); } +static struct device_node *parse_remote_endpoint (struct device_node *np, +const char *prop_name, +int index) +{ +struct device_node *endpoint, *sup; + +if (strcmp (prop_name,"remote-endpoint" )) +return NULL ; + + endpoint =of_parse_phandle (np, prop_name, index); +if (!endpoint) +return NULL ; + + sup =get_remote_endpoint_dev (endpoint); +of_node_put (endpoint); +return sup; +} +static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_clocks, }, { .parse_prop = parse_interconnects, },
Signature · 1 line
2.43.0.594.gd9cf4e227d-goog