7ef4087f99
We have a better idea why the Yoga patches are affecting one touchpad. Bring them back so everyone can benefit from Yoga.
237 lines
6.9 KiB
Diff
237 lines
6.9 KiB
Diff
From 318a1971826103ecf560875b17236dd4a93e8c88 Mon Sep 17 00:00:00 2001
|
|
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
Date: Mon, 30 Nov 2015 17:11:31 +0200
|
|
Subject: [PATCH 03/16] 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>
|
|
---
|
|
drivers/base/property.c | 150 ++++++++++++++++++++++++++++++++++-------------
|
|
include/linux/property.h | 8 +--
|
|
2 files changed, 113 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/drivers/base/property.c b/drivers/base/property.c
|
|
index 2e01f3f..86834bd 100644
|
|
--- a/drivers/base/property.c
|
|
+++ b/drivers/base/property.c
|
|
@@ -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;
|
|
}
|
|
|
|
@@ -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_; \
|
|
@@ -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_; \
|
|
@@ -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);
|
|
@@ -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);
|
|
diff --git a/include/linux/property.h b/include/linux/property.h
|
|
index 0a3705a..c29460a 100644
|
|
--- a/include/linux/property.h
|
|
+++ b/include/linux/property.h
|
|
@@ -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;
|
|
--
|
|
2.5.0
|
|
|