Commit 318a1971 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Rafael J. Wysocki

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: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 61f5e294
...@@ -63,45 +63,107 @@ static struct property_entry *pset_prop_get(struct property_set *pset, ...@@ -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)
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;
}
static int pset_prop_read_u8_array(struct property_set *pset,
const char *propname,
u8 *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_u16_array(struct property_set *pset,
const char *propname,
u16 *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_u32_array(struct property_set *pset,
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) if (!prop)
return -ENODATA;
if (prop->type != type)
return -EPROTO;
if (!val)
return prop->nval;
if (prop->nval < nval)
return -EOVERFLOW;
switch (type) {
case DEV_PROP_U8:
item_size = sizeof(u8);
break;
case DEV_PROP_U16:
item_size = sizeof(u16);
break;
case DEV_PROP_U32:
item_size = sizeof(u32);
break;
case DEV_PROP_U64:
item_size = sizeof(u64);
break;
case DEV_PROP_STRING:
item_size = sizeof(const char *);
break;
default:
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); ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment