public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: Grant Likely <grant.likely@linaro.org>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Arnd Bergmann <arnd@arndb.de>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Aaron Lu <aaron.lu@intel.com>,
	devicetree@vger.kernel.org,
	Linus Walleij <linus.walleij@linaro.org>,
	Alexandre Courbot <gnurou@gmail.com>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Bryan Wu <cooloney@gmail.com>,
	Darren Hart <dvhart@linux.intel.com>,
	Mark Rutland <mark.rutland@arm.com>
Subject: Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
Date: Sat, 18 Oct 2014 16:55:20 +0200	[thread overview]
Message-ID: <20141018145520.6039FC40591@trevor.secretlab.ca> (raw)
In-Reply-To: <1628104.Ek1EGbdVha@vostro.rjw.lan>

On Fri, 17 Oct 2014 14:14:53 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@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.likely@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@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);
> 


  parent reply	other threads:[~2014-10-18 14:55 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-07  0:12 ` [PATCH 01/13] ACPI: Add support for device specific properties Rafael J. Wysocki
2014-10-13 12:47   ` Grant Likely
2014-10-07  0:12 ` [PATCH 02/13] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
2014-10-07  0:13 ` [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
2014-10-14 13:38   ` Grant Likely
2014-10-07  0:14 ` [PATCH 04/13] ACPI: Document ACPI device specific properties Rafael J. Wysocki
2014-10-13 12:41   ` Grant Likely
2014-10-14  9:42     ` Mika Westerberg
2014-10-07  0:14 ` [PATCH 05/13] misc: at25: Make use of device property API Rafael J. Wysocki
2014-10-07  9:10   ` Geert Uytterhoeven
2014-10-07  9:32     ` Mika Westerberg
2014-10-07  0:15 ` [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
2014-10-14 13:44   ` Grant Likely
2014-10-15  8:46     ` Mika Westerberg
2014-10-07  0:15 ` [PATCH 07/13] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
2014-10-07  0:16 ` [PATCH 08/13] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
     [not found] ` <2660541.BycO7TFnA2-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-07  0:16   ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
     [not found]     ` <1740633.d3tSWZ2Q0u-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-07 17:29       ` Dmitry Torokhov
2014-10-07  0:17 ` [PATCH 10/13] Driver core: Child node properties for devices Rafael J. Wysocki
2014-10-07  0:18 ` [PATCH 11/13] gpio: Support for unified device properties interface Rafael J. Wysocki
2014-10-07 10:22   ` Alexandre Courbot
2014-10-07 10:40     ` Mika Westerberg
2014-10-07 10:52       ` Alexandre Courbot
2014-10-08  0:09         ` Rafael J. Wysocki
2014-10-08  2:55           ` Alexandre Courbot
2014-10-08 14:01             ` Rafael J. Wysocki
2014-10-07  0:18 ` [PATCH 12/13] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
2014-10-08 14:04   ` Rafael J. Wysocki
     [not found]     ` <2960802.kPr8UT7PvT-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-08 17:47       ` Bryan Wu
2014-10-08 22:02         ` Rafael J. Wysocki
2014-10-07  0:19 ` [PATCH 13/13] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-07 17:30   ` Dmitry Torokhov
2014-10-07  0:39 ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-07  2:28 ` Greg Kroah-Hartman
2014-10-15 13:04 ` David Woodhouse
2014-10-15 13:15   ` Mark Rutland
2014-10-15 13:28     ` David Woodhouse
2014-10-15 13:42       ` Mark Rutland
2014-10-15 14:08         ` David Woodhouse
2014-10-15 14:46           ` Darren Hart
2014-10-15 15:11             ` David Woodhouse
2014-10-15 15:17             ` Mark Rutland
2014-10-15 15:43               ` Darren Hart
2014-10-16 10:05                 ` Rafael J. Wysocki
2014-10-16 14:55                 ` David Woodhouse
2014-10-18  8:37                   ` Grant Likely
2014-10-18  8:39                   ` Grant Likely
2014-10-18  8:35                 ` Grant Likely
2014-10-21 21:50                   ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties? support Darren Hart
2015-01-14 18:42     ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support David Woodhouse
2015-01-15  9:12       ` Rafael J. Wysocki
2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
2014-10-17 12:03   ` [PATCH v5 01/12] ACPI: Add support for device specific properties Rafael J. Wysocki
2014-10-17 12:04   ` [PATCH v5 02/12] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
2014-10-20  0:07     ` [Update][PATCH " Rafael J. Wysocki
2014-10-17 12:05   ` [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
2014-10-20 14:05     ` Grant Likely
2014-10-20 22:19       ` Rafael J. Wysocki
2014-10-17 12:07   ` [PATCH v5 04/12] misc: at25: Make use of device property API Rafael J. Wysocki
2014-10-17 12:09   ` [PATCH v5 05/12] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
2014-10-17 12:10   ` [PATCH v5 06/12] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
2014-10-17 12:11   ` [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
2014-10-28 15:26     ` Linus Walleij
2014-10-28 21:56       ` Rafael J. Wysocki
2014-10-29  8:53         ` Mika Westerberg
2014-10-30 15:40           ` Linus Walleij
2014-10-30 16:15             ` Mika Westerberg
2014-10-31  9:41               ` Linus Walleij
2014-10-31  9:55                 ` Mika Westerberg
2014-10-30 15:34         ` Linus Walleij
2014-10-17 12:12   ` [PATCH v5 08/12] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-17 12:14   ` [PATCH v5 09/12] Driver core: Unified interface for firmware node properties Rafael J. Wysocki
2014-10-18  9:35     ` Arnd Bergmann
2014-10-19 23:30       ` Rafael J. Wysocki
2014-10-20 14:14         ` Arnd Bergmann
2014-10-18 14:55     ` Grant Likely [this message]
2014-10-19 23:46       ` Rafael J. Wysocki
     [not found]         ` <7821406.D7i8JfDpzX-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-20 14:18           ` Grant Likely
2014-10-20 22:14             ` Rafael J. Wysocki
2014-10-20 14:19         ` Arnd Bergmann
2014-10-20 14:55           ` Grant Likely
2014-10-20 22:22           ` Rafael J. Wysocki
2014-10-19 22:14     ` Greg Kroah-Hartman
2014-10-19 23:31       ` Rafael J. Wysocki
2014-10-20  0:15     ` [Update][PATCH " Rafael J. Wysocki
2014-10-17 12:16   ` [PATCH v5 10/12] gpio: Support for unified device properties interface Rafael J. Wysocki
2014-10-17 18:09     ` Arnd Bergmann
2014-10-18  9:47       ` Arnd Bergmann
2014-10-19 23:58         ` Rafael J. Wysocki
2014-10-20 14:22           ` Arnd Bergmann
2014-10-20  6:12         ` Alexandre Courbot
2014-10-20 14:26           ` Arnd Bergmann
2014-10-17 12:17   ` [PATCH v5 11/12] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
2014-10-17 12:18   ` [PATCH v5 12/12] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-17 12:22   ` [PATCH v5 00/12] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-17 15:40   ` Greg Kroah-Hartman
2014-10-17 19:23     ` Darren Hart
2014-10-17 21:49     ` Rafael J. Wysocki
2014-10-19 22:14       ` Greg Kroah-Hartman
2014-10-17 18:04   ` Arnd Bergmann
2014-10-17 22:50     ` Rafael J. Wysocki
2014-10-18  8:49       ` Grant Likely
2014-10-19 23:32         ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141018145520.6039FC40591@trevor.secretlab.ca \
    --to=grant.likely@linaro.org \
    --cc=aaron.lu@intel.com \
    --cc=arnd@arndb.de \
    --cc=cooloney@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=dvhart@linux.intel.com \
    --cc=gnurou@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mika.westerberg@linux.intel.com \
    --cc=rjw@rjwysocki.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox