summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-05-24 16:34:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-05-24 16:34:14 -0700
commit268db333b561c77dee3feb6831806412293b4a7e (patch)
treeca1b016a6ca2cf9177725c565509dcc4f3e7b445 /drivers/base
parentf4fb8596657c998ca4cdb833bc0f509533a38ddd (diff)
parentf6e109a0afedec2a9470fec31a567071e2f01e46 (diff)
downloadlinux-268db333b561c77dee3feb6831806412293b4a7e.tar.bz2
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.c217
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);