On Fri, 17 Oct 2014 14:14:53 +0200
, "Rafael J. Wysocki" <r...@rjwysocki.net>
 wrote:
> From: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
> 
> Add new generic routines are provided for retrieving properties from
> device description objects in the platform firmware in case there are
> no struct device objects for them (either those objects have not been
> created yet or they do not exist at all).
> 
> The following functions are provided:
> 
> fwnode_property_present()
> fwnode_property_read_u8()
> fwnode_property_read_u16()
> fwnode_property_read_u32()
> fwnode_property_read_u64()
> fwnode_property_read_string()
> fwnode_property_read_u8_array()
> fwnode_property_read_u16_array()
> fwnode_property_read_u32_array()
> fwnode_property_read_u64_array()
> fwnode_property_read_string_array()
> 
> in analogy with the corresponding functions for struct device added
> previously.  For all of them, the first argument is a pointer to struct
> fwnode_handle (new type) that allows a device description object
> (depending on what platform firmware interface is in use) to be
> obtained.
> 
> Add a new macro device_for_each_child_node() for iterating over the
> children of the device description object associated with a given
> device and a new function device_get_child_node_count() returning the
> number of a given device's child nodes.
> 
> The interface covers both ACPI and Device Trees.

This is all *so much* better. I'm a lot happier.

I was about to make the comment that the implementation for
device_property_read_*() should merely be wrappers around
fwnode_property_read_*(), but when when I actually looked at it, I saw
this:

In patch 2:
int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
{
        if (IS_ENABLED(CONFIG_OF) && dev->of_node)
                return of_property_read_u8(dev->of_node, propname, val);

        return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
                                  DEV_PROP_U8, val);
}

And in this patch:
int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
                            u8 *val)
{
        if (is_of_node(fwnode))
                return of_property_read_u8(of_node(fwnode), propname, val);
        else if (is_acpi_node(fwnode))
                return acpi_dev_prop_read(acpi_node(fwnode), propname,
                                          DEV_PROP_U8, val);

        return -ENXIO;
}

Making the device_property functions wrappers around fwnode_property_*
wouldn't actually be great since it would need to decode the fwnode
pointer twice.

I do still think the functions above should be macro generated, just in
terms of keeping the line count down, and I would suggest merging patches #2
and #9.

Something like:

#define define_fwnode_accessors(__type, __devprop_type) \
int device_property_read_##__type(struct device *dev, \
                                const char *propname, __type *val) \
{ \
        if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
                return of_property_read_##__type(dev->of_node, propname, val); \
        return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
                                  __devprop_type, val); \
} \
int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
                                const char *propname, __type *val) \
{ \
        if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
                return of_property_read_##__type(of_node(fwnode), propname, 
val); \
        else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
                return acpi_dev_prop_read(acpi_node(fwnode), propname, \
                                          __devprop_type, val); \
        return -ENXIO; \
}

define_fwnode_accessors(u8, DEV_PROP_U8);
define_fwnode_accessors(u16, DEV_PROP_U16);
define_fwnode_accessors(u32, DEV_PROP_U32);
define_fwnode_accessors(u64, DEV_PROP_U64);

That significantly reduces the code size for these things.

Also, can the non-array versions be implemented as a wrapper around the
array versions? That also will reduce the sheer number of lines of code
a lot.

Maybe this:

#define define_fwnode_accessors(__type, __devprop_type) \
int device_property_read_##__type##_array(struct device *dev, \
                                const char *propname, __type *val, \
                                size_t nval) \
{ \
        if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
                return of_property_read_##__type##_array(dev->of_node, \
                propname, val, nval); \
        return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, \
                                  __devprop_type, val, nval); \
} \
static inline int device_property_read_##__type(struct device *dev, \
                                const char *propname, __type *val) \
{ \
        return device_property_read_##__type##_array(dev, propname, val, 1) \
} \
int fwnode_property_read_##__type##_array(struct fwnode_handle *fwnode, \
                                const char *propname, __type *val, \
                                size_t nval) \
{ \
        if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
                return of_property_read_##__type(of_node(fwnode), propname, 
val, nval); \
        else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
                return acpi_dev_prop_read(acpi_node(fwnode), propname, \
                                          __devprop_type, val, nval); \
        return -ENXIO; \
} \
static inline int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
                                const char *propname, __type *val) \
{ \
        return fwnode_property_read_##__type##_array(fwnode, propname, val, 1) \
}
define_fwnode_accessors(u8, DEV_PROP_U8);
define_fwnode_accessors(u16, DEV_PROP_U16);
define_fwnode_accessors(u32, DEV_PROP_U32);
define_fwnode_accessors(u64, DEV_PROP_U64);

g.

> 
> Suggested-by: Grant Likely <grant.lik...@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
> ---
>  drivers/acpi/scan.c      |   21 ++
>  drivers/base/property.c  |  373 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acpi_bus.h  |   12 +
>  include/linux/acpi.h     |   21 ++
>  include/linux/of.h       |   22 ++
>  include/linux/property.h |   48 ++++++
>  6 files changed, 497 insertions(+)
> 
> Index: linux-pm/include/linux/property.h
> ===================================================================
> --- linux-pm.orig/include/linux/property.h
> +++ linux-pm/include/linux/property.h
> @@ -44,4 +44,52 @@ int device_property_read_u64_array(struc
>  int device_property_read_string_array(struct device *dev, const char 
> *propname,
>                                     char **val, size_t nval);
>  
> +enum fwnode_type {
> +     FWNODE_INVALID = 0,
> +     FWNODE_OF,
> +     FWNODE_ACPI,
> +};
> +
> +struct fwnode_handle {
> +     enum fwnode_type type;
> +};
> +
> +bool fwnode_property_present(struct fwnode_handle *fwnode, const char 
> *propname);
> +int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char 
> *propname,
> +                         u8 *val);
> +int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u16 *val);
> +int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u32 *val);
> +int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u64 *val);
> +int fwnode_property_read_string(struct fwnode_handle *fwnode,
> +                             const char *propname, const char **val);
> +int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
> +                               const char *propname, u8 *val,
> +                               size_t nval);
> +int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u16 *val,
> +                                size_t nval);
> +int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u32 *val,
> +                                size_t nval);
> +int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u64 *val,
> +                                size_t nval);
> +int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
> +                                   const char *propname, char **val,
> +                                   size_t nval);
> +
> +struct fwnode_handle *device_get_next_child_node(struct device *dev,
> +                                              struct fwnode_handle *child);
> +
> +#define device_for_each_child_node(dev, child) \
> +     for (child = device_get_next_child_node(dev, NULL); child; \
> +          child = device_get_next_child_node(dev, child))
> +
> +void fwnode_handle_put(struct fwnode_handle *fwnode);
> +
> +unsigned int device_get_child_node_count(struct device *dev);
> +
>  #endif /* _LINUX_PROPERTY_H_ */
> Index: linux-pm/include/acpi/acpi_bus.h
> ===================================================================
> --- linux-pm.orig/include/acpi/acpi_bus.h
> +++ linux-pm/include/acpi/acpi_bus.h
> @@ -27,6 +27,7 @@
>  #define __ACPI_BUS_H__
>  
>  #include <linux/device.h>
> +#include <linux/property.h>
>  
>  /* TBD: Make dynamic */
>  #define ACPI_MAX_HANDLES     10
> @@ -348,6 +349,7 @@ struct acpi_device_data {
>  struct acpi_device {
>       int device_type;
>       acpi_handle handle;             /* no handle for fixed hardware */
> +     struct fwnode_handle fwnode;
>       struct acpi_device *parent;
>       struct list_head children;
>       struct list_head node;
> @@ -372,6 +374,16 @@ struct acpi_device {
>       void (*remove)(struct acpi_device *);
>  };
>  
> +static inline bool is_acpi_node(struct fwnode_handle *fwnode)
> +{
> +     return fwnode && fwnode->type == FWNODE_ACPI;
> +}
> +
> +static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
> +{
> +     return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
> +}
> +
>  static inline void *acpi_driver_data(struct acpi_device *d)
>  {
>       return d->driver_data;
> Index: linux-pm/include/linux/acpi.h
> ===================================================================
> --- linux-pm.orig/include/linux/acpi.h
> +++ linux-pm/include/linux/acpi.h
> @@ -439,6 +439,18 @@ int acpi_device_modalias(struct device *
>  #define ACPI_COMPANION_SET(dev, adev)        do { } while (0)
>  #define ACPI_HANDLE(dev)             (NULL)
>  
> +struct fwnode_handle;
> +
> +static inline bool is_acpi_node(struct fwnode_handle *fwnode)
> +{
> +     return false;
> +}
> +
> +static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
> +{
> +     return NULL;
> +}
> +
>  static inline const char *acpi_dev_name(struct acpi_device *adev)
>  {
>       return NULL;
> @@ -681,6 +693,9 @@ int acpi_dev_prop_read(struct acpi_devic
>  int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
>                            enum dev_prop_type proptype, void *val,
>                            size_t nval);
> +
> +struct acpi_device *acpi_get_next_child(struct device *dev,
> +                                     struct acpi_device *child);
>  #else
>  static inline int acpi_dev_get_property(struct acpi_device *adev,
>                                       const char *name, acpi_object_type type,
> @@ -724,6 +739,12 @@ static inline int acpi_dev_prop_read_arr
>       return -ENXIO;
>  }
>  
> +static inline struct acpi_device *acpi_get_next_child(struct device *dev,
> +                                                   struct acpi_device *child)
> +{
> +     return NULL;
> +}
> +
>  #endif
>  
>  #endif       /*_LINUX_ACPI_H*/
> Index: linux-pm/include/linux/of.h
> ===================================================================
> --- linux-pm.orig/include/linux/of.h
> +++ linux-pm/include/linux/of.h
> @@ -50,6 +50,7 @@ struct device_node {
>       const char *type;
>       phandle phandle;
>       const char *full_name;
> +     struct fwnode_handle fwnode;
>  
>       struct  property *properties;
>       struct  property *deadprops;    /* removed properties */
> @@ -80,6 +81,7 @@ extern struct kobj_type of_node_ktype;
>  static inline void of_node_init(struct device_node *node)
>  {
>       kobject_init(&node->kobj, &of_node_ktype);
> +     node->fwnode.type = FWNODE_OF;
>  }
>  
>  /* true when node is initialized */
> @@ -115,6 +117,16 @@ extern struct device_node *of_aliases;
>  extern struct device_node *of_stdout;
>  extern raw_spinlock_t devtree_lock;
>  
> +static inline bool is_of_node(struct fwnode_handle *fwnode)
> +{
> +     return fwnode && fwnode->type == FWNODE_OF;
> +}
> +
> +static inline struct device_node *of_node(struct fwnode_handle *fwnode)
> +{
> +     return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
> +}
> +
>  static inline bool of_have_populated_dt(void)
>  {
>       return of_allnodes != NULL;
> @@ -365,6 +377,16 @@ bool of_console_check(struct device_node
>  
>  #else /* CONFIG_OF */
>  
> +static inline bool is_of_node(struct fwnode_handle *fwnode)
> +{
> +     return false;
> +}
> +
> +static inline struct device_node *of_node(struct fwnode_handle *fwnode)
> +{
> +     return NULL;
> +}
> +
>  static inline const char* of_node_full_name(const struct device_node *np)
>  {
>       return "<no-node>";
> Index: linux-pm/drivers/base/property.c
> ===================================================================
> --- linux-pm.orig/drivers/base/property.c
> +++ linux-pm/drivers/base/property.c
> @@ -156,6 +156,166 @@ int device_property_read_string(struct d
>  }
>  EXPORT_SYMBOL_GPL(device_property_read_string);
>  
> +/**
> + * fwnode_property_present - check if a property of a firmware node is 
> present
> + * @fwnode: Firmware node whose property to check
> + * @propname: Name of the property
> + */
> +bool fwnode_property_present(struct fwnode_handle *fwnode, const char 
> *propname)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_bool(of_node(fwnode), propname);
> +     else if (is_acpi_node(fwnode))
> +             return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> +
> +     return false;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_present);
> +
> +/**
> + * fwnode_property_read_u8 - return a u8 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value 
> into
> + * @val if found.  The value is checked to be of type u8.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO or %-EILSEQ if the property type is not u8,
> + *      %-EOVERFLOW if the property value is out of bounds of u8,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char 
> *propname,
> +                         u8 *val)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_u8(of_node(fwnode), propname, val);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +                                       DEV_PROP_U8, val);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u8);
> +
> +/**
> + * fwnode_property_read_u16 - return a u16 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value 
> into
> + * @val if found.  The value is checked to be of type u16.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO or %-EILSEQ if the property type is not u16,
> + *      %-EOVERFLOW if the property value is out of bounds of u16,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u16 *val)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_u16(of_node(fwnode), propname, val);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +                                       DEV_PROP_U16, val);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u16);
> +
> +/**
> + * fwnode_property_read_u32 - return a u32 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value 
> into
> + * @val if found.  The value is checked to be of type u32.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO or %-EILSEQ if the property type is not u32,
> + *      %-EOVERFLOW if the property value is out of bounds of u32,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u32 *val)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_u32(of_node(fwnode), propname, val);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +                                       DEV_PROP_U32, val);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u32);
> +
> +/**
> + * fwnode_property_read_u64 - return a u64 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value 
> into
> + * @val if found.  The value is checked to be of type u64.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO or %-EILSEQ if the property type is not u64,
> + *      %-EOVERFLOW if the property value is out of bounds of u64,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char 
> *propname,
> +                          u64 *val)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_u64(of_node(fwnode), propname, val);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +                                       DEV_PROP_U64, val);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u64);
> +
> +/**
> + * fwnode_property_read_string - return a string property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value 
> into
> + * @val if found.  The value is checked to be a string.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO or %-EILSEQ if the property is not a string,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_string(struct fwnode_handle *fwnode,
> +                             const char *propname, const char **val)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_string(of_node(fwnode), propname, val);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +                                       DEV_PROP_STRING, val);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_string);
> +
>  #define of_dev_prop_read_array(node, propname, type, val, nval) \
>       (val) ? of_property_read_##type##_array((node), (propname), (val), 
> (nval)) \
>             : of_property_count_elems_of_size((node), (propname), 
> sizeof(type))
> @@ -299,3 +459,216 @@ int device_property_read_string_array(st
>                                       DEV_PROP_STRING, val, nval);
>  }
>  EXPORT_SYMBOL_GPL(device_property_read_string_array);
> +
> +/**
> + * fwnode_property_read_u8_array - return a u8 array property of firmware 
> node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u8 properties with @propname from @fwnode and stores 
> them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO if the property is not an array of numbers,
> + *      %-EOVERFLOW if the size of the property is not as expected,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
> +                               const char *propname, u8 *val, size_t nval)
> +{
> +     if (is_of_node(fwnode))
> +             return of_dev_prop_read_array(of_node(fwnode), propname,
> +                                           u8, val, nval);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +                                             DEV_PROP_U8, val, nval);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
> +
> +/**
> + * fwnode_property_read_u16_array - return a u16 array property of firmware 
> node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u16 properties with @propname from @fwnode and store 
> them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO if the property is not an array of numbers,
> + *      %-EOVERFLOW if the size of the property is not as expected,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u16 *val, size_t nval)
> +{
> +     if (is_of_node(fwnode))
> +             return of_dev_prop_read_array(of_node(fwnode), propname,
> +                                           u16, val, nval);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +                                             DEV_PROP_U16, val, nval);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
> +
> +/**
> + * fwnode_property_read_u32_array - return a u32 array property of firmware 
> node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u32 properties with @propname from @fwnode store them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO if the property is not an array of numbers,
> + *      %-EOVERFLOW if the size of the property is not as expected,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u32 *val, size_t nval)
> +{
> +     if (is_of_node(fwnode))
> +             return of_dev_prop_read_array(of_node(fwnode), propname,
> +                                           u32, val, nval);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +                                             DEV_PROP_U32, val, nval);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
> +
> +/**
> + * fwnode_property_read_u64_array - return a u64 array property firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u64 properties with @propname from @fwnode and store 
> them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO if the property is not an array of numbers,
> + *      %-EOVERFLOW if the size of the property is not as expected,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
> +                                const char *propname, u64 *val, size_t nval)
> +{
> +     if (is_of_node(fwnode))
> +             return of_dev_prop_read_array(of_node(fwnode), propname,
> +                                           u64, val, nval);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +                                             DEV_PROP_U64, val, nval);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
> +
> +/**
> + * fwnode_property_read_string_array - return string array property of a node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an string list property @propname from the given firmware node and 
> store
> + * them to @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *      %-EINVAL if given arguments are not valid,
> + *      %-ENODATA if the property does not have a value,
> + *      %-EPROTO if the property is not an array of strings,
> + *      %-EOVERFLOW if the size of the property is not as expected,
> + *      %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
> +                                   const char *propname, char **val,
> +                                   size_t nval)
> +{
> +     if (is_of_node(fwnode))
> +             return of_property_read_string_array(of_node(fwnode), propname,
> +                                                  val, nval);
> +     else if (is_acpi_node(fwnode))
> +             return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +                                             DEV_PROP_STRING, val, nval);
> +
> +     return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
> +
> +
> +/**
> + * device_get_next_child_node - Return the next child node handle for a 
> device
> + * @dev: Device to find the next child node for.
> + * @child: Handle to one of the device's child nodes or a null handle.
> + */
> +struct fwnode_handle *device_get_next_child_node(struct device *dev,
> +                                              struct fwnode_handle *child)
> +{
> +     if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
> +             struct device_node *node;
> +
> +             node = of_get_next_available_child(dev->of_node, 
> of_node(child));
> +             if (node)
> +                     return &node->fwnode;
> +     } else if (ACPI_COMPANION(dev)) {
> +             struct acpi_device *node;
> +
> +             node = acpi_get_next_child(dev, acpi_node(child));
> +             if (node)
> +                     return &node->fwnode;
> +     }
> +     return NULL;
> +}
> +EXPORT_SYMBOL_GPL(device_get_next_child_node);
> +
> +/**
> + * fwnode_handle_put - Drop reference to a device node
> + * @fwnode: Pointer to the device node to drop the reference to.
> + *
> + * This has to be used when terminating device_for_each_child_node() 
> iteration
> + * with break or return to prevent stale device node references from being 
> left
> + * behind.
> + */
> +void fwnode_handle_put(struct fwnode_handle *fwnode)
> +{
> +     if (is_of_node(fwnode))
> +             of_node_put(of_node(fwnode));
> +}
> +EXPORT_SYMBOL_GPL(fwnode_handle_put);
> +
> +/**
> + * device_get_child_node_count - return the number of child nodes for device
> + * @dev: Device to cound the child nodes for
> + */
> +unsigned int device_get_child_node_count(struct device *dev)
> +{
> +     struct fwnode_handle *child;
> +     unsigned int count = 0;
> +
> +     device_for_each_child_node(dev, child)
> +             count++;
> +
> +     return count;
> +}
> +EXPORT_SYMBOL_GPL(device_get_child_node_count);
> Index: linux-pm/drivers/acpi/scan.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/scan.c
> +++ linux-pm/drivers/acpi/scan.c
> @@ -1342,6 +1342,26 @@ int acpi_device_add(struct acpi_device *
>       return result;
>  }
>  
> +struct acpi_device *acpi_get_next_child(struct device *dev,
> +                                     struct acpi_device *child)
> +{
> +     struct acpi_device *adev = ACPI_COMPANION(dev);
> +     struct list_head *head, *next;
> +
> +     if (!adev)
> +             return NULL;
> +
> +     head = &adev->children;
> +     if (list_empty(head))
> +             return NULL;
> +
> +     if (!child)
> +             return list_first_entry(head, struct acpi_device, node);
> +
> +     next = child->node.next;
> +     return next == head ? NULL : list_entry(next, struct acpi_device, node);
> +}
> +
>  /* --------------------------------------------------------------------------
>                                   Driver Management
>     
> -------------------------------------------------------------------------- */
> @@ -1961,6 +1981,7 @@ void acpi_init_device_object(struct acpi
>       device->device_type = type;
>       device->handle = handle;
>       device->parent = acpi_bus_get_parent(handle);
> +     device->fwnode.type = FWNODE_ACPI;
>       acpi_set_device_status(device, sta);
>       acpi_device_get_busid(device);
>       acpi_set_pnp_ids(handle, &device->pnp, type);
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to