Skip to content

Commit

Permalink
device property: refactor built-in properties support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Shevchenko authored and Rafael J. Wysocki committed Dec 7, 2015
1 parent 61f5e29 commit 318a197
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 45 deletions.
150 changes: 110 additions & 40 deletions drivers/base/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,45 +63,107 @@ static struct property_entry *pset_prop_get(struct property_set *pset,
return NULL;
}

static int pset_prop_read_array(struct property_set *pset, const char *name,
enum dev_prop_type type, void *val, size_t nval)
static void *pset_prop_find(struct property_set *pset, const char *propname,
size_t length)
{
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)
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;
}
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;
}

Expand Down Expand Up @@ -314,6 +376,10 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
: 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_) \
({ \
int _ret_; \
Expand All @@ -324,8 +390,8 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
_val_, _nval_); \
else if (is_pset_node(_fwnode_)) \
_ret_ = pset_prop_read_array(to_pset_node(_fwnode_), _propname_, \
_proptype_, _val_, _nval_); \
_ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \
_type_, _val_, _nval_); \
else \
_ret_ = -ENXIO; \
_ret_; \
Expand Down Expand Up @@ -466,8 +532,12 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
val, nval);
else if (is_pset_node(fwnode))
return pset_prop_read_array(to_pset_node(fwnode), propname,
DEV_PROP_STRING, val, nval);
return val ?
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;
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
Expand Down Expand Up @@ -496,8 +566,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
val, 1);
else if (is_pset_node(fwnode))
return pset_prop_read_array(to_pset_node(fwnode), propname,
DEV_PROP_STRING, val, 1);
return pset_prop_read_string_array(to_pset_node(fwnode),
propname, val, 1);
return -ENXIO;
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string);
Expand Down
8 changes: 3 additions & 5 deletions include/linux/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,12 @@ static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
/**
* struct property_entry - "Built-in" device property representation.
* @name: Name of the property.
* @type: Type of the property.
* @nval: Number of items of type @type making up the value.
* @value: Value of the property (an array of @nval items of type @type).
* @length: Length of data making up the value.
* @value: Value of the property (an array of items of the given type).
*/
struct property_entry {
const char *name;
enum dev_prop_type type;
size_t nval;
size_t length;
union {
void *raw_data;
u8 *u8_data;
Expand Down

0 comments on commit 318a197

Please sign in to comment.