diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 02:34:14 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 02:34:14 +0300 |
commit | 268db333b561c77dee3feb6831806412293b4a7e (patch) | |
tree | ca1b016a6ca2cf9177725c565509dcc4f3e7b445 /drivers/base | |
parent | f4fb8596657c998ca4cdb833bc0f509533a38ddd (diff) | |
parent | f6e109a0afedec2a9470fec31a567071e2f01e46 (diff) | |
download | linux-268db333b561c77dee3feb6831806412293b4a7e.tar.xz |
Merge tag 'devprop-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull device properties framework updates from Rafael Wysocki:
"These mostly extend the device property API and make it easier to use
in some cases.
Specifics:
- Allow error pointer to be passed to fwnode APIs (Andy Shevchenko).
- Introduce fwnode_for_each_parent_node() (Andy Shevchenko, Douglas
Anderson).
- Advertise fwnode and device property count API calls (Andy
Shevchenko).
- Clean up fwnode_is_ancestor_of() (Andy Shevchenko).
- Convert device_{dma_supported,get_dma_attr} to fwnode (Sakari
Ailus).
- Release subnode properties with data nodes (Sakari Ailus).
- Add ->iomap() and ->irq_get() to fwnode operations (Sakari Ailus)"
* tag 'devprop-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
device property: Advertise fwnode and device property count API calls
device property: Fix recent breakage of fwnode_get_next_parent_dev()
device property: Drop 'test' prefix in parameters of fwnode_is_ancestor_of()
device property: Introduce fwnode_for_each_parent_node()
device property: Allow error pointer to be passed to fwnode APIs
ACPI: property: Release subnode properties with data nodes
device property: Add irq_get to fwnode operation
device property: Add iomap to fwnode operations
ACPI: property: Move acpi_fwnode_device_get_match_data() up
device property: Convert device_{dma_supported,get_dma_attr} to fwnode
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/property.c | 217 |
1 files changed, 115 insertions, 102 deletions
diff --git a/drivers/base/property.c b/drivers/base/property.c index c0e94cce9c29..3adcac2c78fa 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -47,12 +47,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); @@ -66,6 +68,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_present); * Function reads an array of u8 properties with @propname from the device * firmware description and stores them to @val if found. * + * It's recommended to call device_property_count_u8() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -91,6 +96,9 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array); * Function reads an array of u16 properties with @propname from the device * firmware description and stores them to @val if found. * + * It's recommended to call device_property_count_u16() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -116,6 +124,9 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array); * Function reads an array of u32 properties with @propname from the device * firmware description and stores them to @val if found. * + * It's recommended to call device_property_count_u32() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -141,6 +152,9 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array); * Function reads an array of u64 properties with @propname from the device * firmware description and stores them to @val if found. * + * It's recommended to call device_property_count_u64() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -166,6 +180,9 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array); * Function reads an array of string properties with @propname from the device * firmware description and stores them to @val if found. * + * It's recommended to call device_property_string_array_count() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values read on success if @val is non-NULL, * number of values available on success if @val is NULL, * %-EINVAL if given arguments are not valid, @@ -232,15 +249,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); } /** @@ -253,6 +271,9 @@ static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode, * Read an array of u8 properties with @propname from @fwnode and stores them to * @val if found. * + * It's recommended to call fwnode_property_count_u8() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -279,6 +300,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); * Read an array of u16 properties with @propname from @fwnode and store them to * @val if found. * + * It's recommended to call fwnode_property_count_u16() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -305,6 +329,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); * Read an array of u32 properties with @propname from @fwnode store them to * @val if found. * + * It's recommended to call fwnode_property_count_u32() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -331,6 +358,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); * Read an array of u64 properties with @propname from @fwnode and store them to * @val if found. * + * It's recommended to call fwnode_property_count_u64() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values if @val was %NULL, * %0 if the property was found (success), * %-EINVAL if given arguments are not valid, @@ -357,6 +387,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); * Read an string list property @propname from the given firmware node and store * them to @val if found. * + * It's recommended to call fwnode_property_string_array_count() instead of calling + * this function with @val equals %NULL and @nval equals 0. + * * Return: number of values read on success if @val is non-NULL, * number of values available on success if @val is NULL, * %-EINVAL if given arguments are not valid, @@ -371,14 +404,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); @@ -480,15 +515,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); @@ -587,17 +626,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; - dev = get_dev_from_fwnode(fwnode); - } while (!dev); - fwnode_handle_put(fwnode); - return dev; + fwnode_for_each_parent_node(fwnode, parent) { + dev = get_dev_from_fwnode(parent); + if (dev) { + fwnode_handle_put(parent); + return dev; + } + } + return NULL; } /** @@ -608,13 +647,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; } @@ -635,40 +672,43 @@ EXPORT_SYMBOL_GPL(fwnode_count_parents); struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode, unsigned int depth) { - unsigned int i; + struct fwnode_handle *parent; - fwnode_handle_get(fwnode); + if (depth == 0) + return fwnode_handle_get(fwnode); - for (i = 0; i < depth && fwnode; i++) - fwnode = fwnode_get_next_parent(fwnode); - - return fwnode; + fwnode_for_each_parent_node(fwnode, parent) { + if (--depth == 0) + return parent; + } + return NULL; } 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 + * fwnode_is_ancestor_of - Test if @ancestor is ancestor of @child + * @ancestor: Firmware which is tested for being an ancestor + * @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. + * Returns true if @ancestor is an ancestor of @child. Otherwise, returns false. */ -bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor, - struct fwnode_handle *test_child) +bool fwnode_is_ancestor_of(struct fwnode_handle *ancestor, struct fwnode_handle *child) { - if (!test_ancestor) + struct fwnode_handle *parent; + + if (IS_ERR_OR_NULL(ancestor)) return false; - fwnode_handle_get(test_child); - while (test_child) { - if (test_child == test_ancestor) { - fwnode_handle_put(test_child); + if (child == ancestor) + return true; + + fwnode_for_each_parent_node(child, parent) { + if (parent == ancestor) { + fwnode_handle_put(parent); return true; } - test_child = fwnode_get_next_parent(test_child); } return false; } @@ -698,7 +738,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 { @@ -722,16 +762,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); @@ -798,6 +838,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; @@ -823,33 +866,16 @@ 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_of_node(fwnode)) - return true; - - return acpi_dma_supported(to_acpi_device_node(fwnode)); + return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported); } 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_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(to_acpi_device_node(fwnode)); + if (!fwnode_has_op(dev_fwnode(dev), device_get_dma_attr)) + return DEV_DMA_NOT_SUPPORTED; - return attr; + return fwnode_call_int_op(dev_fwnode(dev), device_get_dma_attr); } EXPORT_SYMBOL_GPL(device_get_dma_attr); @@ -904,10 +930,7 @@ EXPORT_SYMBOL_GPL(device_get_phy_mode); */ void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index) { - if (IS_ENABLED(CONFIG_OF_ADDRESS) && is_of_node(fwnode)) - return of_iomap(to_of_node(fwnode), index); - - return NULL; + return fwnode_call_ptr_op(fwnode, iomap, index); } EXPORT_SYMBOL(fwnode_iomap); @@ -921,17 +944,7 @@ EXPORT_SYMBOL(fwnode_iomap); */ int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index) { - struct resource res; - int ret; - - 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) - return ret; - - return res.start; + return fwnode_call_int_op(fwnode, irq_get, index); } EXPORT_SYMBOL(fwnode_irq_get); @@ -988,14 +1001,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); |