FAILED: patch "[PATCH] device property: Allow secondary lookup in" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 2692c614f8f05929d692b3dbfd3faef1f00fbaf0
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026031703-caravan-bladder-c63a@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2692c614f8f05929d692b3dbfd3faef1f00fbaf0 Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <[email protected]>
Date: Tue, 10 Feb 2026 14:58:22 +0100
Subject: [PATCH] device property: Allow secondary lookup in
fwnode_get_next_child_node()
When device_get_child_node_count() got split to the fwnode and device respective APIs, the fwnode didn't inherit the ability to traverse over the secondary fwnode. Hence any user, that switches from device to fwnode API misses this feature. In particular, this was revealed by the commit 1490cbb9dbfd ("device property: Split fwnode_get_child_node_count()") that effectively broke the GPIO enumeration on Intel Galileo boards. Fix this by moving the secondary lookup from device to fwnode API.
Note, in general no device_*() API should go into the depth of the fwnode implementation.
drivers/base/property.c +13 -14
@@ -797,7 +797,18 @@ struct fwnode_handle * fwnode_get_next_child_node(const struct fwnode_handle *fwnode, struct fwnode_handle *child) { - return fwnode_call_ptr_op(fwnode, get_next_child_node, child); + struct fwnode_handle *next; + +if (IS_ERR_OR_NULL (fwnode)) +return NULL ; + +/* Try to find a child in primary fwnode */ + next =fwnode_call_ptr_op (fwnode, get_next_child_node, child); +if (next) +return next; + +/* When no more children in primary, continue with secondary */ +return fwnode_call_ptr_op (fwnode->secondary, get_next_child_node, child); }EXPORT_SYMBOL_GPL (fwnode_get_next_child_node);
@@ -841,19 +852,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);struct fwnode_handle *device_get_next_child_node (const struct device *dev,struct fwnode_handle *child) { -const struct fwnode_handle *fwnode =dev_fwnode (dev); -struct fwnode_handle *next; - -if (IS_ERR_OR_NULL (fwnode)) -return NULL ; - -/* Try to find a child in primary fwnode */ - next =fwnode_get_next_child_node (fwnode, child); -if (next) -return next; - -/* When no more children in primary, continue with secondary */ -return fwnode_get_next_child_node (fwnode->secondary, child); +return fwnode_get_next_child_node (dev_fwnode (dev), child); }EXPORT_SYMBOL_GPL (device_get_next_child_node);
Sasha Levin
maintainerPATCH 1/8 device property: Add fwnode_is_ancestor_of() and fwnode_get_next_parent_dev()
From: Saravana Kannan <[email protected]>
[ Upstream commit b5d3e2fbcb10957521af14c4256cd0e5f68b9234 ]
Add fwnode_is_ancestor_of() helper function to check if a fwnode is an ancestor of another fwnode.
Add fwnode_get_next_parent_dev() helper function that take as input a fwnode and finds the closest ancestor fwnode that has a corresponding struct device and returns that struct device.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 52 ++++++++++++++++++++++++++++++++++++++++ include/linux/property.h | 3 +++ 2 files changed, 55 insertions(+)
drivers/base/property.c +52 -0
@@ -614,6 +614,31 @@ struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode) }EXPORT_SYMBOL_GPL (fwnode_get_next_parent); +/** +* fwnode_get_next_parent_dev - Find device of closest ancestor fwnode +* @fwnode: firmware node +* +* Given a firmware node (@fwnode), this function finds its closest ancestor +* firmware node that has a corresponding struct device and returns that struct +* device. +* +* The caller of this function is expected to call put_device() on the returned +* device when they are done. +*/ +struct device *fwnode_get_next_parent_dev (struct fwnode_handle *fwnode) +{ +struct device *dev =NULL ; + +fwnode_handle_get (fwnode); +do { + fwnode =fwnode_get_next_parent (fwnode); +if (fwnode) + dev =get_dev_from_fwnode (fwnode); + }while (fwnode && !dev); +fwnode_handle_put (fwnode); +return dev; +} +/** * fwnode_count_parents - Return the number of parents a node has * @fwnode: The node the parents of which are to be counted
@@ -660,6 +685,33 @@ struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode, }EXPORT_SYMBOL_GPL (fwnode_get_nth_parent); +/** +* fwnode_is_ancestor_of - Test if @test_ancestor is ancestor of @test_child +* @test_ancestor: Firmware which is tested for being an ancestor +* @test_child: Firmware which is tested for being the child +* +* A node is considered an ancestor of itself too. +* +* Returns true if @test_ancestor is an ancestor of @test_child. +* Otherwise, returns false. +*/ +bool fwnode_is_ancestor_of (struct fwnode_handle *test_ancestor, +struct fwnode_handle *test_child) +{ +if (!test_ancestor) +return false; + +fwnode_handle_get (test_child); +while (test_child) { +if (test_child == test_ancestor) { +fwnode_handle_put (test_child); +return true; + } + test_child =fwnode_get_next_parent (test_child); + } +return false; +} +/** * fwnode_get_next_child_node - Return the next child node handle for a node * @fwnode: Firmware node to find the next child node for.
include/linux/property.h +3 -0
@@ -85,9 +85,12 @@ 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 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,unsigned int depth); +bool fwnode_is_ancestor_of (struct fwnode_handle *test_ancestor, +struct fwnode_handle *test_child);struct fwnode_handle *fwnode_get_next_child_node (const struct fwnode_handle *fwnode,struct fwnode_handle *child); struct fwnode_handle *fwnode_get_next_available_child_node(
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/8 media: device property: Return true in fwnode_device_is_available for NULL ops
From: Daniel Scally <[email protected]>
[ Upstream commit 5273382d03763277aaf8c6a2d6088e2afaee0cf0 ]
Some types of fwnode_handle do not implement the device_is_available() check, such as those created by software_nodes. There isn't really a meaningful way to check for the availability of a device that doesn't actually exist, so if the check isn't implemented just assume that the "device" is present.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/base/property.c +6 -0
@@ -837,9 +837,15 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);/** * fwnode_device_is_available - check if a device is available for use * @fwnode: Pointer to the fwnode of the device. +* +* For fwnode node types that don't implement the .device_is_available() +* operation, this function returns true. */ bool fwnode_device_is_available (const struct fwnode_handle *fwnode) { +if (!fwnode_has_op (fwnode, device_is_available)) +return true; +return fwnode_call_bool_op (fwnode, device_is_available); }EXPORT_SYMBOL_GPL (fwnode_device_is_available);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 3/8 device property: Retrieve fwnode from of_node via accessor
In reply to Sasha LevinFrom: Andy Shevchenko <[email protected]>
[ Upstream commit 3cd8015040d7537a6b88e26f36768a90d9247829 ]
OF provides a specific accessor to retrieve fwnode handle. Use it instead of direct dereferencing.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/base/property.c +2 -2
@@ -21,7 +21,7 @@struct fwnode_handle *dev_fwnode (const struct device *dev) {return IS_ENABLED (CONFIG_OF ) && dev->of_node ? - &dev->of_node->fwnode : dev->fwnode; +of_fwnode_handle (dev->of_node) : dev->fwnode; }EXPORT_SYMBOL_GPL (dev_fwnode);
@@ -763,7 +763,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,struct fwnode_handle *fwnode =NULL , *next;if (dev->of_node) - fwnode = &dev->of_node->fwnode; + fwnode =of_fwnode_handle (dev->of_node);else if (adev) fwnode =acpi_fwnode_handle (adev);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 4/8 device property: Unify access to of_node
In reply to Sasha LevinFrom: Andy Shevchenko <[email protected]>
[ Upstream commit fb38f314fbd173e2e9f9f0f2e720a5f4889562da ]
Historically we have a few variants how we access dev->fwnode and dev->of_node. Some of the functions during development gained different versions of the getters. Unify access to of_node and as a side change slightly refactor ACPI specific branches.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 29 +++++++++++++---------------- include/linux/property.h | 2 +- 2 files changed, 14 insertions(+), 17 deletions(-)
drivers/base/property.c +13 -16
@@ -759,13 +759,8 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);struct fwnode_handle *device_get_next_child_node (struct device *dev,struct fwnode_handle *child) { -struct acpi_device *adev =ACPI_COMPANION (dev); -struct fwnode_handle *fwnode =NULL , *next; - -if (dev->of_node) - fwnode =of_fwnode_handle (dev->of_node); -else if (adev) - fwnode =acpi_fwnode_handle (adev); +const struct fwnode_handle *fwnode =dev_fwnode (dev); +struct fwnode_handle *next;/* Try to find a child in primary fwnode */ next =fwnode_get_next_child_node (fwnode, child);
@@ -868,28 +863,31 @@ EXPORT_SYMBOL_GPL(device_get_child_node_count);bool device_dma_supported (struct device *dev) { +const struct fwnode_handle *fwnode =dev_fwnode (dev); +/* For DT, this is always supported. * For ACPI, this depends on CCA, which * is determined by the acpi_dma_supported(). */ -if (IS_ENABLED (CONFIG_OF ) && dev->of_node) +if (is_of_node (fwnode))return true; -return acpi_dma_supported (ACPI_COMPANION (dev)); +return acpi_dma_supported (to_acpi_device_node (fwnode)); }EXPORT_SYMBOL_GPL (device_dma_supported);enum dev_dma_attr device_get_dma_attr (struct device *dev) { +const struct fwnode_handle *fwnode =dev_fwnode (dev);enum dev_dma_attr attr =DEV_DMA_NOT_SUPPORTED ; -if (IS_ENABLED (CONFIG_OF ) && dev->of_node) { -if (of_dma_is_coherent (dev->of_node)) +if (is_of_node (fwnode)) { +if (of_dma_is_coherent (to_of_node (fwnode))) attr =DEV_DMA_COHERENT ;else attr =DEV_DMA_NON_COHERENT ; }else - attr =acpi_get_dma_attr (ACPI_COMPANION (dev)); + attr =acpi_get_dma_attr (to_acpi_device_node (fwnode));return attr; }
@@ -1007,14 +1005,13 @@ EXPORT_SYMBOL(device_get_mac_address);* Returns Linux IRQ number on success. Other values are determined * accordingly to acpi_/of_ irq_get() operation. */ -int fwnode_irq_get (struct fwnode_handle *fwnode,unsigned int index) +int fwnode_irq_get (const struct fwnode_handle *fwnode,unsigned int index) { -struct device_node *of_node =to_of_node (fwnode);struct resource res;int ret; -if (IS_ENABLED (CONFIG_OF ) && of_node) -return of_irq_get (of_node, index); +if (is_of_node (fwnode)) +return of_irq_get (to_of_node (fwnode), index); ret =acpi_irq_get (ACPI_HANDLE_FWNODE (fwnode), index, &res);if (ret)
include/linux/property.h +1 -1
@@ -119,7 +119,7 @@ struct fwnode_handle *device_get_named_child_node(struct device *dev,struct fwnode_handle *fwnode_handle_get (struct fwnode_handle *fwnode);void fwnode_handle_put (struct fwnode_handle *fwnode); -int fwnode_irq_get (struct fwnode_handle *fwnode,unsigned int index); +int fwnode_irq_get (const struct fwnode_handle *fwnode,unsigned int index);unsigned int device_get_child_node_count (struct device *dev);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 5/8 device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()
In reply to Sasha LevinFrom: Daniel Scally <[email protected]>
[ Upstream commit b5b41ab6b0c1bb70fe37a0d193006c969e3b5909 ]
Sensor drivers often check for an endpoint to make sure that they're connected to a consuming device like a CIO2 during .probe(). Some of those endpoints might be in the form of software_nodes assigned as a secondary to the device's fwnode_handle. Account for this possibility in fwnode_graph_get_next_endpoint() to avoid having to do it in the sensor drivers themselves.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
drivers/base/property.c +20 -1
@@ -1033,7 +1033,26 @@ struct fwnode_handle * fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, struct fwnode_handle *prev) { - return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev); + const struct fwnode_handle *parent; +struct fwnode_handle *ep; + +/* +* If this function is in a loop and the previous iteration returned +* an endpoint from fwnode->secondary, then we need to use the secondary +* as parent rather than @fwnode. +*/ +if (prev) + parent =fwnode_graph_get_port_parent (prev); +else + parent = fwnode; + + ep =fwnode_call_ptr_op (parent, graph_get_next_endpoint, prev); + +if (IS_ERR_OR_NULL (ep) && + !IS_ERR_OR_NULL (parent) && !IS_ERR_OR_NULL (parent->secondary)) + ep =fwnode_graph_get_next_endpoint (parent->secondary,NULL ); + +return ep; }EXPORT_SYMBOL_GPL (fwnode_graph_get_next_endpoint);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 6/8 device property: Check fwnode->secondary when finding properties
In reply to Sasha LevinFrom: Daniel Scally <[email protected]>
[ Upstream commit c097af1d0a8483b44fa30e86b311991d76b6ae67 ]
fwnode_property_get_reference_args() searches for named properties against a fwnode_handle, but these could instead be against the fwnode's secondary. If the property isn't found against the primary, check the secondary to see if it's there instead.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/base/property.c +11 -2
@@ -479,8 +479,17 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, unsigned int nargs, unsigned int index, struct fwnode_reference_args *args) { - return fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop, -nargs ,index ,args ); + int ret; + + ret =fwnode_call_int_op (fwnode, get_reference_args, prop, nargs_prop, + nargs, index, args); + +if (ret <0 && !IS_ERR_OR_NULL (fwnode) && + !IS_ERR_OR_NULL (fwnode->secondary)) + ret =fwnode_call_int_op (fwnode->secondary, get_reference_args, + prop, nargs_prop, nargs, index, args); + +return ret; }EXPORT_SYMBOL_GPL (fwnode_property_get_reference_args);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 7/8 device property: Allow error pointer to be passed to fwnode APIs
In reply to Sasha LevinFrom: Andy Shevchenko <[email protected]>
[ Upstream commit 002752af7b89b74c64fe6bec8c5fde3d3a7810d8 ]
Some of the fwnode APIs might return an error pointer instead of NULL or valid fwnode handle. The result of such API call may be considered optional and hence the test for it is usually done in a form of
fwnode = fwnode_find_reference(...); if (IS_ERR(fwnode)) ...error handling...
Nevertheless the resulting fwnode may have bumped the reference count and hence caller of the above API is obliged to call fwnode_handle_put(). Since fwnode may be not valid either as NULL or error pointer the check has to be performed there. This approach uglifies the code and adds a point of making a mistake, i.e. forgetting about error point case.
To prevent this, allow an error pointer to be passed to the fwnode APIs.
Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
--- drivers/base/property.c | 89 +++++++++++++++++++++++------------------ include/linux/fwnode.h | 10 ++--- 2 files changed, 56 insertions(+), 43 deletions(-)
drivers/base/property.c +51 -38
@@ -48,12 +48,14 @@ bool fwnode_property_present(const struct fwnode_handle *fwnode, {bool ret; +if (IS_ERR_OR_NULL (fwnode)) +return false; + ret =fwnode_call_bool_op (fwnode, property_present, propname); -if (ret == false && !IS_ERR_OR_NULL (fwnode) && - !IS_ERR_OR_NULL (fwnode->secondary)) - ret =fwnode_call_bool_op (fwnode->secondary, property_present, - propname); -return ret; +if (ret) +return ret; + +return fwnode_call_bool_op (fwnode->secondary, property_present, propname); }EXPORT_SYMBOL_GPL (fwnode_property_present);
@@ -233,15 +235,16 @@ static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode, {int ret; +if (IS_ERR_OR_NULL (fwnode)) +return -EINVAL ; + ret =fwnode_call_int_op (fwnode, property_read_int_array, propname, elem_size, val, nval); -if (ret == -EINVAL && !IS_ERR_OR_NULL (fwnode) && - !IS_ERR_OR_NULL (fwnode->secondary)) - ret =fwnode_call_int_op ( - fwnode->secondary, property_read_int_array, propname, - elem_size, val, nval); +if (ret != -EINVAL ) +return ret; -return ret; +return fwnode_call_int_op (fwnode->secondary, property_read_int_array, propname, + elem_size, val, nval); }/**
@@ -372,14 +375,16 @@ int fwnode_property_read_string_array(const struct fwnode_handle *fwnode, {int ret; +if (IS_ERR_OR_NULL (fwnode)) +return -EINVAL ; + ret =fwnode_call_int_op (fwnode, property_read_string_array, propname, val, nval); -if (ret == -EINVAL && !IS_ERR_OR_NULL (fwnode) && - !IS_ERR_OR_NULL (fwnode->secondary)) - ret =fwnode_call_int_op (fwnode->secondary, - property_read_string_array, propname, - val, nval); -return ret; +if (ret != -EINVAL ) +return ret; + +return fwnode_call_int_op (fwnode->secondary, property_read_string_array, propname, + val, nval); }EXPORT_SYMBOL_GPL (fwnode_property_read_string_array);
@@ -481,15 +486,19 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, {int ret; +if (IS_ERR_OR_NULL (fwnode)) +return -ENOENT ; + ret =fwnode_call_int_op (fwnode, get_reference_args, prop, nargs_prop, nargs, index, args); +if (ret ==0 ) +return ret; -if (ret <0 && !IS_ERR_OR_NULL (fwnode) && - !IS_ERR_OR_NULL (fwnode->secondary)) - ret =fwnode_call_int_op (fwnode->secondary, get_reference_args, - prop, nargs_prop, nargs, index, args); +if (IS_ERR_OR_NULL (fwnode->secondary)) +return ret; -return ret; +return fwnode_call_int_op (fwnode->secondary, get_reference_args, prop, nargs_prop, + nargs, index, args); }EXPORT_SYMBOL_GPL (fwnode_property_get_reference_args);
@@ -683,12 +692,13 @@ EXPORT_SYMBOL_GPL(fwnode_count_parents);struct fwnode_handle *fwnode_get_nth_parent (struct fwnode_handle *fwnode,unsigned int depth) { -unsigned int i; -fwnode_handle_get (fwnode); -for (i =0 ; i < depth && fwnode; i++) +do { +if (depth-- ==0 ) +break ; fwnode =fwnode_get_next_parent (fwnode); + }while (fwnode);return fwnode; }
@@ -707,17 +717,17 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);bool fwnode_is_ancestor_of (struct fwnode_handle *test_ancestor,struct fwnode_handle *test_child) { -if (!test_ancestor) +if (IS_ERR_OR_NULL (test_ancestor))return false;fwnode_handle_get (test_child); -while (test_child) { +do {if (test_child == test_ancestor) {fwnode_handle_put (test_child);return true; } test_child =fwnode_get_next_parent (test_child); - } + }while (test_child);return false; }
@@ -746,7 +756,7 @@ fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode, {struct fwnode_handle *next_child = child; -if (!fwnode) +if (IS_ERR_OR_NULL (fwnode))return NULL ; do {
@@ -771,16 +781,16 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,const struct fwnode_handle *fwnode =dev_fwnode (dev);struct fwnode_handle *next; +if (IS_ERR_OR_NULL (fwnode)) +return NULL ; +/* Try to find a child in primary fwnode */ next =fwnode_get_next_child_node (fwnode, child);if (next)return next;/* When no more children in primary, continue with secondary */ -if (fwnode && !IS_ERR_OR_NULL (fwnode->secondary)) - next =fwnode_get_next_child_node (fwnode->secondary, child); - -return next; +return fwnode_get_next_child_node (fwnode->secondary, child); }EXPORT_SYMBOL_GPL (device_get_next_child_node);
@@ -847,6 +857,9 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);*/ bool fwnode_device_is_available (const struct fwnode_handle *fwnode) { +if (IS_ERR_OR_NULL (fwnode)) +return false; +if (!fwnode_has_op (fwnode, device_is_available))return true;
@@ -1054,14 +1067,14 @@ fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, parent =fwnode_graph_get_port_parent (prev); else parent = fwnode; +if (IS_ERR_OR_NULL (parent)) +return NULL ; ep =fwnode_call_ptr_op (parent, graph_get_next_endpoint, prev); +if (ep) +return ep; -if (IS_ERR_OR_NULL (ep) && - !IS_ERR_OR_NULL (parent) && !IS_ERR_OR_NULL (parent->secondary)) - ep =fwnode_graph_get_next_endpoint (parent->secondary,NULL ); - -return ep; +return fwnode_graph_get_next_endpoint (parent->secondary,NULL ); }EXPORT_SYMBOL_GPL (fwnode_graph_get_next_endpoint);
include/linux/fwnode.h +5 -5
@@ -149,12 +149,12 @@ struct fwnode_operations { struct device *dev); }; -#define fwnode_has_op (fwnode, op) \ - ((fwnode) && (fwnode)->ops && (fwnode)->ops->op) +#define fwnode_has_op (fwnode, op) \ + (!IS_ERR_OR_NULL(fwnode) && (fwnode)->ops && (fwnode)->ops->op) +#define fwnode_call_int_op (fwnode, op, ...) \ - (fwnode ? (fwnode_has_op(fwnode, op) ? \ - (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ - -EINVAL) + (fwnode_has_op(fwnode, op) ? \ + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : (IS_ERR_OR_NULL(fwnode) ? -EINVAL : -ENXIO))#define fwnode_call_bool_op (fwnode, op, ...) \ (fwnode_has_op(fwnode, op) ? \
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 8/8 device property: Allow secondary lookup in fwnode_get_next_child_node()
In reply to Sasha LevinFrom: Andy Shevchenko <[email protected]>
[ Upstream commit 2692c614f8f05929d692b3dbfd3faef1f00fbaf0 ]
When device_get_child_node_count() got split to the fwnode and device respective APIs, the fwnode didn't inherit the ability to traverse over the secondary fwnode. Hence any user, that switches from device to fwnode API misses this feature. In particular, this was revealed by the commit 1490cbb9dbfd ("device property: Split fwnode_get_child_node_count()") that effectively broke the GPIO enumeration on Intel Galileo boards. Fix this by moving the secondary lookup from device to fwnode API.
Note, in general no device_*() API should go into the depth of the fwnode implementation.
--- drivers/base/property.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-)
drivers/base/property.c +13 -14
@@ -740,7 +740,18 @@ struct fwnode_handle * fwnode_get_next_child_node(const struct fwnode_handle *fwnode, struct fwnode_handle *child) { - return fwnode_call_ptr_op(fwnode, get_next_child_node, child); + struct fwnode_handle *next; + +if (IS_ERR_OR_NULL (fwnode)) +return NULL ; + +/* Try to find a child in primary fwnode */ + next =fwnode_call_ptr_op (fwnode, get_next_child_node, child); +if (next) +return next; + +/* When no more children in primary, continue with secondary */ +return fwnode_call_ptr_op (fwnode->secondary, get_next_child_node, child); }EXPORT_SYMBOL_GPL (fwnode_get_next_child_node);
@@ -778,19 +789,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);struct fwnode_handle *device_get_next_child_node (struct device *dev,struct fwnode_handle *child) { -const struct fwnode_handle *fwnode =dev_fwnode (dev); -struct fwnode_handle *next; - -if (IS_ERR_OR_NULL (fwnode)) -return NULL ; - -/* Try to find a child in primary fwnode */ - next =fwnode_get_next_child_node (fwnode, child); -if (next) -return next; - -/* When no more children in primary, continue with secondary */ -return fwnode_get_next_child_node (fwnode->secondary, child); +return fwnode_get_next_child_node (dev_fwnode (dev), child); }EXPORT_SYMBOL_GPL (device_get_next_child_node);
Signature · 1 line
2.51.0