[PATCH v2 06/17] xen/device-tree: Add dt_property_read_variable_u32_array helper

Rahul Singh posted 17 patches 3 years, 2 months ago
There is a newer version of this series
[PATCH v2 06/17] xen/device-tree: Add dt_property_read_variable_u32_array helper
Posted by Rahul Singh 3 years, 2 months ago
Based on tag Linux v5.14.2 commit bbdd3de144fc142f2f4b9834c9241cc4e7f3d3fc

Import the Linux helper of_property_read_variable_u32_array. This
function find and read an array of 32 bit integers from a property,
with bounds on the minimum and maximum array size.

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
---
Change in v2: Patch introduced in v2
---
 xen/common/device_tree.c      | 61 +++++++++++++++++++++++++++++++++++
 xen/include/xen/device_tree.h | 26 +++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 03d25a81ce..53160d61f8 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -208,6 +208,67 @@ int dt_property_read_string(const struct dt_device_node *np,
     return 0;
 }
 
+/**
+ * dt_find_property_value_of_size
+ *
+ * @np:     device node from which the property value is to be read.
+ * @propname:   name of the property to be searched.
+ * @min:    minimum allowed length of property value
+ * @max:    maximum allowed length of property value (0 means unlimited)
+ * @len:    if !=NULL, actual length is written to here
+ *
+ * Search for a property in a device node and valid the requested size.
+ *
+ * Return: The property value on success, -EINVAL if the property does not
+ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data is too small or too large.
+ */
+static void *dt_find_property_value_of_size(const struct dt_device_node *np,
+                                            const char *propname, u32 min,
+                                            u32 max, size_t *len)
+{
+    const struct dt_property *prop = dt_find_property(np, propname, NULL);
+
+    if ( !prop )
+        return ERR_PTR(-EINVAL);
+    if ( !prop->value )
+        return ERR_PTR(-ENODATA);
+    if ( prop->length < min )
+        return ERR_PTR(-EOVERFLOW);
+    if ( max && prop->length > max )
+        return ERR_PTR(-EOVERFLOW);
+
+    if ( len )
+        *len = prop->length;
+
+    return prop->value;
+}
+
+int dt_property_read_variable_u32_array(const struct dt_device_node *np,
+                                        const char *propname, u32 *out_values,
+                                        size_t sz_min, size_t sz_max)
+{
+    size_t sz, count;
+    const __be32 *val = dt_find_property_value_of_size(np, propname,
+                        (sz_min * sizeof(*out_values)),
+                        (sz_max * sizeof(*out_values)),
+                        &sz);
+
+    if ( IS_ERR(val) )
+        return PTR_ERR(val);
+
+    if ( !sz_max )
+        sz = sz_min;
+    else
+        sz /= sizeof(*out_values);
+
+    count = sz;
+    while ( count-- )
+        *out_values++ = be32_to_cpup(val++);
+
+    return sz;
+}
+
 int dt_property_match_string(const struct dt_device_node *np,
                              const char *propname, const char *string)
 {
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index b02696be94..1693fb8e8c 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -366,6 +366,32 @@ bool_t dt_property_read_u32(const struct dt_device_node *np,
 bool_t dt_property_read_u64(const struct dt_device_node *np,
                             const char *name, u64 *out_value);
 
+
+/**
+ * dt_property_read_variable_u32_array - Find and read an array of 32 bit
+ * integers from a property, with bounds on the minimum and maximum array size.
+ *
+ * @np:     device node from which the property value is to be read.
+ * @propname:   name of the property to be searched.
+ * @out_values: pointer to return found values.
+ * @sz_min: minimum number of array elements to read
+ * @sz_max: maximum number of array elements to read, if zero there is no
+ *      upper limit on the number of elements in the dts entry but only
+ *      sz_min will be read.
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it.
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
+ *
+ * The out_values is modified only if a valid u32 value can be decoded.
+ */
+int dt_property_read_variable_u32_array(const struct dt_device_node *np,
+                                        const char *propname, u32 *out_values,
+                                        size_t sz_min, size_t sz_max);
+
 /**
  * dt_property_read_bool - Check if a property exists
  * @np: node to get the value
-- 
2.17.1


Re: [PATCH v2 06/17] xen/device-tree: Add dt_property_read_variable_u32_array helper
Posted by Stefano Stabellini 3 years, 2 months ago
On Wed, 22 Sep 2021, Rahul Singh wrote:
> Based on tag Linux v5.14.2 commit bbdd3de144fc142f2f4b9834c9241cc4e7f3d3fc

I'd prefer the upstream commit id if possible, not one based on the
stable trees (the commit id doesn't resolve at all on Linus's tree).
Aside from that, the patch is fine.


> Import the Linux helper of_property_read_variable_u32_array. This
> function find and read an array of 32 bit integers from a property,
> with bounds on the minimum and maximum array size.
> 
> Signed-off-by: Rahul Singh <rahul.singh@arm.com>
> ---
> Change in v2: Patch introduced in v2
> ---
>  xen/common/device_tree.c      | 61 +++++++++++++++++++++++++++++++++++
>  xen/include/xen/device_tree.h | 26 +++++++++++++++
>  2 files changed, 87 insertions(+)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 03d25a81ce..53160d61f8 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -208,6 +208,67 @@ int dt_property_read_string(const struct dt_device_node *np,
>      return 0;
>  }
>  
> +/**
> + * dt_find_property_value_of_size
> + *
> + * @np:     device node from which the property value is to be read.
> + * @propname:   name of the property to be searched.
> + * @min:    minimum allowed length of property value
> + * @max:    maximum allowed length of property value (0 means unlimited)
> + * @len:    if !=NULL, actual length is written to here
> + *
> + * Search for a property in a device node and valid the requested size.
> + *
> + * Return: The property value on success, -EINVAL if the property does not
> + * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
> + * property data is too small or too large.
> + */
> +static void *dt_find_property_value_of_size(const struct dt_device_node *np,
> +                                            const char *propname, u32 min,
> +                                            u32 max, size_t *len)
> +{
> +    const struct dt_property *prop = dt_find_property(np, propname, NULL);
> +
> +    if ( !prop )
> +        return ERR_PTR(-EINVAL);
> +    if ( !prop->value )
> +        return ERR_PTR(-ENODATA);
> +    if ( prop->length < min )
> +        return ERR_PTR(-EOVERFLOW);
> +    if ( max && prop->length > max )
> +        return ERR_PTR(-EOVERFLOW);
> +
> +    if ( len )
> +        *len = prop->length;
> +
> +    return prop->value;
> +}
> +
> +int dt_property_read_variable_u32_array(const struct dt_device_node *np,
> +                                        const char *propname, u32 *out_values,
> +                                        size_t sz_min, size_t sz_max)
> +{
> +    size_t sz, count;
> +    const __be32 *val = dt_find_property_value_of_size(np, propname,
> +                        (sz_min * sizeof(*out_values)),
> +                        (sz_max * sizeof(*out_values)),
> +                        &sz);
> +
> +    if ( IS_ERR(val) )
> +        return PTR_ERR(val);
> +
> +    if ( !sz_max )
> +        sz = sz_min;
> +    else
> +        sz /= sizeof(*out_values);
> +
> +    count = sz;
> +    while ( count-- )
> +        *out_values++ = be32_to_cpup(val++);
> +
> +    return sz;
> +}
> +
>  int dt_property_match_string(const struct dt_device_node *np,
>                               const char *propname, const char *string)
>  {
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index b02696be94..1693fb8e8c 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -366,6 +366,32 @@ bool_t dt_property_read_u32(const struct dt_device_node *np,
>  bool_t dt_property_read_u64(const struct dt_device_node *np,
>                              const char *name, u64 *out_value);
>  
> +
> +/**
> + * dt_property_read_variable_u32_array - Find and read an array of 32 bit
> + * integers from a property, with bounds on the minimum and maximum array size.
> + *
> + * @np:     device node from which the property value is to be read.
> + * @propname:   name of the property to be searched.
> + * @out_values: pointer to return found values.
> + * @sz_min: minimum number of array elements to read
> + * @sz_max: maximum number of array elements to read, if zero there is no
> + *      upper limit on the number of elements in the dts entry but only
> + *      sz_min will be read.
> + *
> + * Search for a property in a device node and read 32-bit value(s) from
> + * it.
> + *
> + * Return: The number of elements read on success, -EINVAL if the property
> + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
> + * if the property data is smaller than sz_min or longer than sz_max.
> + *
> + * The out_values is modified only if a valid u32 value can be decoded.
> + */
> +int dt_property_read_variable_u32_array(const struct dt_device_node *np,
> +                                        const char *propname, u32 *out_values,
> +                                        size_t sz_min, size_t sz_max);
> +
>  /**
>   * dt_property_read_bool - Check if a property exists
>   * @np: node to get the value
> -- 
> 2.17.1
> 

Re: [PATCH v2 06/17] xen/device-tree: Add dt_property_read_variable_u32_array helper
Posted by Rahul Singh 3 years, 2 months ago
Hi Stefano,

> On 23 Sep 2021, at 12:06 am, Stefano Stabellini <sstabellini@kernel.org> wrote:
> 
> On Wed, 22 Sep 2021, Rahul Singh wrote:
>> Based on tag Linux v5.14.2 commit bbdd3de144fc142f2f4b9834c9241cc4e7f3d3fc
> 
> I'd prefer the upstream commit id if possible, not one based on the
> stable trees (the commit id doesn't resolve at all on Linus's tree).
> Aside from that, the patch is fine.
> 

Ok. I will change the stable commit id to  upstream commit id.

Regards,
Rahul
> 
>> Import the Linux helper of_property_read_variable_u32_array. This
>> function find and read an array of 32 bit integers from a property,
>> with bounds on the minimum and maximum array size.
>> 
>> Signed-off-by: Rahul Singh <rahul.singh@arm.com>
>> ---
>> Change in v2: Patch introduced in v2
>> ---
>> xen/common/device_tree.c      | 61 +++++++++++++++++++++++++++++++++++
>> xen/include/xen/device_tree.h | 26 +++++++++++++++
>> 2 files changed, 87 insertions(+)
>> 
>> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
>> index 03d25a81ce..53160d61f8 100644
>> --- a/xen/common/device_tree.c
>> +++ b/xen/common/device_tree.c
>> @@ -208,6 +208,67 @@ int dt_property_read_string(const struct dt_device_node *np,
>>     return 0;
>> }
>> 
>> +/**
>> + * dt_find_property_value_of_size
>> + *
>> + * @np:     device node from which the property value is to be read.
>> + * @propname:   name of the property to be searched.
>> + * @min:    minimum allowed length of property value
>> + * @max:    maximum allowed length of property value (0 means unlimited)
>> + * @len:    if !=NULL, actual length is written to here
>> + *
>> + * Search for a property in a device node and valid the requested size.
>> + *
>> + * Return: The property value on success, -EINVAL if the property does not
>> + * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
>> + * property data is too small or too large.
>> + */
>> +static void *dt_find_property_value_of_size(const struct dt_device_node *np,
>> +                                            const char *propname, u32 min,
>> +                                            u32 max, size_t *len)
>> +{
>> +    const struct dt_property *prop = dt_find_property(np, propname, NULL);
>> +
>> +    if ( !prop )
>> +        return ERR_PTR(-EINVAL);
>> +    if ( !prop->value )
>> +        return ERR_PTR(-ENODATA);
>> +    if ( prop->length < min )
>> +        return ERR_PTR(-EOVERFLOW);
>> +    if ( max && prop->length > max )
>> +        return ERR_PTR(-EOVERFLOW);
>> +
>> +    if ( len )
>> +        *len = prop->length;
>> +
>> +    return prop->value;
>> +}
>> +
>> +int dt_property_read_variable_u32_array(const struct dt_device_node *np,
>> +                                        const char *propname, u32 *out_values,
>> +                                        size_t sz_min, size_t sz_max)
>> +{
>> +    size_t sz, count;
>> +    const __be32 *val = dt_find_property_value_of_size(np, propname,
>> +                        (sz_min * sizeof(*out_values)),
>> +                        (sz_max * sizeof(*out_values)),
>> +                        &sz);
>> +
>> +    if ( IS_ERR(val) )
>> +        return PTR_ERR(val);
>> +
>> +    if ( !sz_max )
>> +        sz = sz_min;
>> +    else
>> +        sz /= sizeof(*out_values);
>> +
>> +    count = sz;
>> +    while ( count-- )
>> +        *out_values++ = be32_to_cpup(val++);
>> +
>> +    return sz;
>> +}
>> +
>> int dt_property_match_string(const struct dt_device_node *np,
>>                              const char *propname, const char *string)
>> {
>> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
>> index b02696be94..1693fb8e8c 100644
>> --- a/xen/include/xen/device_tree.h
>> +++ b/xen/include/xen/device_tree.h
>> @@ -366,6 +366,32 @@ bool_t dt_property_read_u32(const struct dt_device_node *np,
>> bool_t dt_property_read_u64(const struct dt_device_node *np,
>>                             const char *name, u64 *out_value);
>> 
>> +
>> +/**
>> + * dt_property_read_variable_u32_array - Find and read an array of 32 bit
>> + * integers from a property, with bounds on the minimum and maximum array size.
>> + *
>> + * @np:     device node from which the property value is to be read.
>> + * @propname:   name of the property to be searched.
>> + * @out_values: pointer to return found values.
>> + * @sz_min: minimum number of array elements to read
>> + * @sz_max: maximum number of array elements to read, if zero there is no
>> + *      upper limit on the number of elements in the dts entry but only
>> + *      sz_min will be read.
>> + *
>> + * Search for a property in a device node and read 32-bit value(s) from
>> + * it.
>> + *
>> + * Return: The number of elements read on success, -EINVAL if the property
>> + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
>> + * if the property data is smaller than sz_min or longer than sz_max.
>> + *
>> + * The out_values is modified only if a valid u32 value can be decoded.
>> + */
>> +int dt_property_read_variable_u32_array(const struct dt_device_node *np,
>> +                                        const char *propname, u32 *out_values,
>> +                                        size_t sz_min, size_t sz_max);
>> +
>> /**
>>  * dt_property_read_bool - Check if a property exists
>>  * @np: node to get the value
>> -- 
>> 2.17.1
>>