mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	device property: refactor built-in properties support
Instead of using the type and nval fields we will use length (in bytes) of the value. The sanity check is done in the accessors. The built-in property accessors are split in the same way such as device tree. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									61f5e294b8
								
							
						
					
					
						commit
						318a197182
					
				
					 2 changed files with 109 additions and 41 deletions
				
			
		| 
						 | 
					@ -63,45 +63,107 @@ static struct property_entry *pset_prop_get(struct property_set *pset,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pset_prop_read_array(struct property_set *pset, const char *name,
 | 
					static void *pset_prop_find(struct property_set *pset, const char *propname,
 | 
				
			||||||
				enum dev_prop_type type, void *val, size_t nval)
 | 
								    size_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct property_entry *prop;
 | 
						struct property_entry *prop;
 | 
				
			||||||
	unsigned int item_size;
 | 
						void *pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prop = pset_prop_get(pset, name);
 | 
						prop = pset_prop_get(pset, propname);
 | 
				
			||||||
	if (!prop)
 | 
						if (!prop)
 | 
				
			||||||
		return -ENODATA;
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
						pointer = prop->value.raw_data;
 | 
				
			||||||
 | 
						if (!pointer)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENODATA);
 | 
				
			||||||
 | 
						if (length > prop->length)
 | 
				
			||||||
 | 
							return ERR_PTR(-EOVERFLOW);
 | 
				
			||||||
 | 
						return pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (prop->type != type)
 | 
					static int pset_prop_read_u8_array(struct property_set *pset,
 | 
				
			||||||
		return -EPROTO;
 | 
									   const char *propname,
 | 
				
			||||||
 | 
									   u8 *values, size_t nval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *pointer;
 | 
				
			||||||
 | 
						size_t length = nval * sizeof(*values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!val)
 | 
						pointer = pset_prop_find(pset, propname, length);
 | 
				
			||||||
		return prop->nval;
 | 
						if (IS_ERR(pointer))
 | 
				
			||||||
 | 
							return PTR_ERR(pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (prop->nval < nval)
 | 
						memcpy(values, pointer, length);
 | 
				
			||||||
		return -EOVERFLOW;
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (type) {
 | 
					static int pset_prop_read_u16_array(struct property_set *pset,
 | 
				
			||||||
	case DEV_PROP_U8:
 | 
									    const char *propname,
 | 
				
			||||||
		item_size = sizeof(u8);
 | 
									    u16 *values, size_t nval)
 | 
				
			||||||
		break;
 | 
					{
 | 
				
			||||||
	case DEV_PROP_U16:
 | 
						void *pointer;
 | 
				
			||||||
		item_size = sizeof(u16);
 | 
						size_t length = nval * sizeof(*values);
 | 
				
			||||||
		break;
 | 
					
 | 
				
			||||||
	case DEV_PROP_U32:
 | 
						pointer = pset_prop_find(pset, propname, length);
 | 
				
			||||||
		item_size = sizeof(u32);
 | 
						if (IS_ERR(pointer))
 | 
				
			||||||
		break;
 | 
							return PTR_ERR(pointer);
 | 
				
			||||||
	case DEV_PROP_U64:
 | 
					
 | 
				
			||||||
		item_size = sizeof(u64);
 | 
						memcpy(values, pointer, length);
 | 
				
			||||||
		break;
 | 
						return 0;
 | 
				
			||||||
	case DEV_PROP_STRING:
 | 
					}
 | 
				
			||||||
		item_size = sizeof(const char *);
 | 
					
 | 
				
			||||||
		break;
 | 
					static int pset_prop_read_u32_array(struct property_set *pset,
 | 
				
			||||||
	default:
 | 
									    const char *propname,
 | 
				
			||||||
 | 
									    u32 *values, size_t nval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *pointer;
 | 
				
			||||||
 | 
						size_t length = nval * sizeof(*values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer = pset_prop_find(pset, propname, length);
 | 
				
			||||||
 | 
						if (IS_ERR(pointer))
 | 
				
			||||||
 | 
							return PTR_ERR(pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(values, pointer, length);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pset_prop_read_u64_array(struct property_set *pset,
 | 
				
			||||||
 | 
									    const char *propname,
 | 
				
			||||||
 | 
									    u64 *values, size_t nval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *pointer;
 | 
				
			||||||
 | 
						size_t length = nval * sizeof(*values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer = pset_prop_find(pset, propname, length);
 | 
				
			||||||
 | 
						if (IS_ERR(pointer))
 | 
				
			||||||
 | 
							return PTR_ERR(pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(values, pointer, length);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pset_prop_count_elems_of_size(struct property_set *pset,
 | 
				
			||||||
 | 
										 const char *propname, size_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct property_entry *prop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prop = pset_prop_get(pset, propname);
 | 
				
			||||||
 | 
						if (!prop)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	memcpy(val, prop->value.raw_data, nval * item_size);
 | 
						return prop->length / length;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pset_prop_read_string_array(struct property_set *pset,
 | 
				
			||||||
 | 
									       const char *propname,
 | 
				
			||||||
 | 
									       const char **strings, size_t nval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *pointer;
 | 
				
			||||||
 | 
						size_t length = nval * sizeof(*strings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer = pset_prop_find(pset, propname, length);
 | 
				
			||||||
 | 
						if (IS_ERR(pointer))
 | 
				
			||||||
 | 
							return PTR_ERR(pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(strings, pointer, length);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -314,6 +376,10 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
 | 
				
			||||||
	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
 | 
						(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
 | 
				
			||||||
	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
 | 
						      : of_property_count_elems_of_size((node), (propname), sizeof(type))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval)				\
 | 
				
			||||||
 | 
						(val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval))	\
 | 
				
			||||||
 | 
						      : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
 | 
					#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
 | 
				
			||||||
({ \
 | 
					({ \
 | 
				
			||||||
	int _ret_; \
 | 
						int _ret_; \
 | 
				
			||||||
| 
						 | 
					@ -324,8 +390,8 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
 | 
				
			||||||
		_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
 | 
							_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
 | 
				
			||||||
					    _val_, _nval_); \
 | 
										    _val_, _nval_); \
 | 
				
			||||||
	else if (is_pset_node(_fwnode_)) 						\
 | 
						else if (is_pset_node(_fwnode_)) 						\
 | 
				
			||||||
		_ret_ = pset_prop_read_array(to_pset_node(_fwnode_), _propname_,	\
 | 
							_ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_,	\
 | 
				
			||||||
					     _proptype_, _val_, _nval_); \
 | 
										     _type_, _val_, _nval_);			\
 | 
				
			||||||
	else \
 | 
						else \
 | 
				
			||||||
		_ret_ = -ENXIO; \
 | 
							_ret_ = -ENXIO; \
 | 
				
			||||||
	_ret_; \
 | 
						_ret_; \
 | 
				
			||||||
| 
						 | 
					@ -466,8 +532,12 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
 | 
				
			||||||
		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
 | 
							return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
 | 
				
			||||||
					   val, nval);
 | 
										   val, nval);
 | 
				
			||||||
	else if (is_pset_node(fwnode))
 | 
						else if (is_pset_node(fwnode))
 | 
				
			||||||
		return pset_prop_read_array(to_pset_node(fwnode), propname,
 | 
							return val ?
 | 
				
			||||||
					    DEV_PROP_STRING, val, nval);
 | 
								pset_prop_read_string_array(to_pset_node(fwnode),
 | 
				
			||||||
 | 
											    propname, val, nval) :
 | 
				
			||||||
 | 
								pset_prop_count_elems_of_size(to_pset_node(fwnode),
 | 
				
			||||||
 | 
											      propname,
 | 
				
			||||||
 | 
											      sizeof(const char *));
 | 
				
			||||||
	return -ENXIO;
 | 
						return -ENXIO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
 | 
					EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
 | 
				
			||||||
| 
						 | 
					@ -496,8 +566,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
 | 
				
			||||||
		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
 | 
							return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
 | 
				
			||||||
					   val, 1);
 | 
										   val, 1);
 | 
				
			||||||
	else if (is_pset_node(fwnode))
 | 
						else if (is_pset_node(fwnode))
 | 
				
			||||||
		return pset_prop_read_array(to_pset_node(fwnode), propname,
 | 
							return pset_prop_read_string_array(to_pset_node(fwnode),
 | 
				
			||||||
					    DEV_PROP_STRING, val, 1);
 | 
											   propname, val, 1);
 | 
				
			||||||
	return -ENXIO;
 | 
						return -ENXIO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(fwnode_property_read_string);
 | 
					EXPORT_SYMBOL_GPL(fwnode_property_read_string);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,14 +144,12 @@ static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * struct property_entry - "Built-in" device property representation.
 | 
					 * struct property_entry - "Built-in" device property representation.
 | 
				
			||||||
 * @name: Name of the property.
 | 
					 * @name: Name of the property.
 | 
				
			||||||
 * @type: Type of the property.
 | 
					 * @length: Length of data making up the value.
 | 
				
			||||||
 * @nval: Number of items of type @type making up the value.
 | 
					 * @value: Value of the property (an array of items of the given type).
 | 
				
			||||||
 * @value: Value of the property (an array of @nval items of type @type).
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct property_entry {
 | 
					struct property_entry {
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
	enum dev_prop_type type;
 | 
						size_t length;
 | 
				
			||||||
	size_t nval;
 | 
					 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		void *raw_data;
 | 
							void *raw_data;
 | 
				
			||||||
		u8 *u8_data;
 | 
							u8 *u8_data;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue