aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 13:13:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 13:13:13 -0400
commita74e0c4c9cb02d44bc5ec1a70a6ba599366fb130 (patch)
tree5c55e103af8770a8b9dcfff48e8bac0074ecd083
parentf4fe74cc909bf811cd9cc7fd84f5a7514e06a7e1 (diff)
parent63dcc7090137a893322432e156d66be3ce104615 (diff)
Merge tag 'dp-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull device properties framework update from Rafael Wysocki: "Modify the device properties framework to remove union aliasing from it (Andy Shevchenko)" * tag 'dp-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: device property: Get rid of union aliasing
-rw-r--r--drivers/base/property.c104
-rw-r--r--drivers/firmware/efi/apple-properties.c8
-rw-r--r--include/linux/property.h52
3 files changed, 117 insertions, 47 deletions
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 8f205f6461ed..240ab5230ff6 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -56,6 +56,72 @@ pset_prop_get(const struct property_set *pset, const char *name)
56 return NULL; 56 return NULL;
57} 57}
58 58
59static const void *property_get_pointer(const struct property_entry *prop)
60{
61 switch (prop->type) {
62 case DEV_PROP_U8:
63 if (prop->is_array)
64 return prop->pointer.u8_data;
65 return &prop->value.u8_data;
66 case DEV_PROP_U16:
67 if (prop->is_array)
68 return prop->pointer.u16_data;
69 return &prop->value.u16_data;
70 case DEV_PROP_U32:
71 if (prop->is_array)
72 return prop->pointer.u32_data;
73 return &prop->value.u32_data;
74 case DEV_PROP_U64:
75 if (prop->is_array)
76 return prop->pointer.u64_data;
77 return &prop->value.u64_data;
78 case DEV_PROP_STRING:
79 if (prop->is_array)
80 return prop->pointer.str;
81 return &prop->value.str;
82 default:
83 return NULL;
84 }
85}
86
87static void property_set_pointer(struct property_entry *prop, const void *pointer)
88{
89 switch (prop->type) {
90 case DEV_PROP_U8:
91 if (prop->is_array)
92 prop->pointer.u8_data = pointer;
93 else
94 prop->value.u8_data = *((u8 *)pointer);
95 break;
96 case DEV_PROP_U16:
97 if (prop->is_array)
98 prop->pointer.u16_data = pointer;
99 else
100 prop->value.u16_data = *((u16 *)pointer);
101 break;
102 case DEV_PROP_U32:
103 if (prop->is_array)
104 prop->pointer.u32_data = pointer;
105 else
106 prop->value.u32_data = *((u32 *)pointer);
107 break;
108 case DEV_PROP_U64:
109 if (prop->is_array)
110 prop->pointer.u64_data = pointer;
111 else
112 prop->value.u64_data = *((u64 *)pointer);
113 break;
114 case DEV_PROP_STRING:
115 if (prop->is_array)
116 prop->pointer.str = pointer;
117 else
118 prop->value.str = pointer;
119 break;
120 default:
121 break;
122 }
123}
124
59static const void *pset_prop_find(const struct property_set *pset, 125static const void *pset_prop_find(const struct property_set *pset,
60 const char *propname, size_t length) 126 const char *propname, size_t length)
61{ 127{
@@ -65,10 +131,7 @@ static const void *pset_prop_find(const struct property_set *pset,
65 prop = pset_prop_get(pset, propname); 131 prop = pset_prop_get(pset, propname);
66 if (!prop) 132 if (!prop)
67 return ERR_PTR(-EINVAL); 133 return ERR_PTR(-EINVAL);
68 if (prop->is_array) 134 pointer = property_get_pointer(prop);
69 pointer = prop->pointer.raw_data;
70 else
71 pointer = &prop->value.raw_data;
72 if (!pointer) 135 if (!pointer)
73 return ERR_PTR(-ENODATA); 136 return ERR_PTR(-ENODATA);
74 if (length > prop->length) 137 if (length > prop->length)
@@ -698,16 +761,17 @@ EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
698 761
699static void property_entry_free_data(const struct property_entry *p) 762static void property_entry_free_data(const struct property_entry *p)
700{ 763{
764 const void *pointer = property_get_pointer(p);
701 size_t i, nval; 765 size_t i, nval;
702 766
703 if (p->is_array) { 767 if (p->is_array) {
704 if (p->is_string && p->pointer.str) { 768 if (p->type == DEV_PROP_STRING && p->pointer.str) {
705 nval = p->length / sizeof(const char *); 769 nval = p->length / sizeof(const char *);
706 for (i = 0; i < nval; i++) 770 for (i = 0; i < nval; i++)
707 kfree(p->pointer.str[i]); 771 kfree(p->pointer.str[i]);
708 } 772 }
709 kfree(p->pointer.raw_data); 773 kfree(pointer);
710 } else if (p->is_string) { 774 } else if (p->type == DEV_PROP_STRING) {
711 kfree(p->value.str); 775 kfree(p->value.str);
712 } 776 }
713 kfree(p->name); 777 kfree(p->name);
@@ -716,7 +780,7 @@ static void property_entry_free_data(const struct property_entry *p)
716static int property_copy_string_array(struct property_entry *dst, 780static int property_copy_string_array(struct property_entry *dst,
717 const struct property_entry *src) 781 const struct property_entry *src)
718{ 782{
719 char **d; 783 const char **d;
720 size_t nval = src->length / sizeof(*d); 784 size_t nval = src->length / sizeof(*d);
721 int i; 785 int i;
722 786
@@ -734,40 +798,44 @@ static int property_copy_string_array(struct property_entry *dst,
734 } 798 }
735 } 799 }
736 800
737 dst->pointer.raw_data = d; 801 dst->pointer.str = d;
738 return 0; 802 return 0;
739} 803}
740 804
741static int property_entry_copy_data(struct property_entry *dst, 805static int property_entry_copy_data(struct property_entry *dst,
742 const struct property_entry *src) 806 const struct property_entry *src)
743{ 807{
808 const void *pointer = property_get_pointer(src);
809 const void *new;
744 int error; 810 int error;
745 811
746 if (src->is_array) { 812 if (src->is_array) {
747 if (!src->length) 813 if (!src->length)
748 return -ENODATA; 814 return -ENODATA;
749 815
750 if (src->is_string) { 816 if (src->type == DEV_PROP_STRING) {
751 error = property_copy_string_array(dst, src); 817 error = property_copy_string_array(dst, src);
752 if (error) 818 if (error)
753 return error; 819 return error;
820 new = dst->pointer.str;
754 } else { 821 } else {
755 dst->pointer.raw_data = kmemdup(src->pointer.raw_data, 822 new = kmemdup(pointer, src->length, GFP_KERNEL);
756 src->length, GFP_KERNEL); 823 if (!new)
757 if (!dst->pointer.raw_data)
758 return -ENOMEM; 824 return -ENOMEM;
759 } 825 }
760 } else if (src->is_string) { 826 } else if (src->type == DEV_PROP_STRING) {
761 dst->value.str = kstrdup(src->value.str, GFP_KERNEL); 827 new = kstrdup(src->value.str, GFP_KERNEL);
762 if (!dst->value.str && src->value.str) 828 if (!new && src->value.str)
763 return -ENOMEM; 829 return -ENOMEM;
764 } else { 830 } else {
765 dst->value.raw_data = src->value.raw_data; 831 new = pointer;
766 } 832 }
767 833
768 dst->length = src->length; 834 dst->length = src->length;
769 dst->is_array = src->is_array; 835 dst->is_array = src->is_array;
770 dst->is_string = src->is_string; 836 dst->type = src->type;
837
838 property_set_pointer(dst, new);
771 839
772 dst->name = kstrdup(src->name, GFP_KERNEL); 840 dst->name = kstrdup(src->name, GFP_KERNEL);
773 if (!dst->name) 841 if (!dst->name)
diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c
index adaa9a3714b9..60a95719ecb8 100644
--- a/drivers/firmware/efi/apple-properties.c
+++ b/drivers/firmware/efi/apple-properties.c
@@ -13,6 +13,9 @@
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Note, all properties are considered as u8 arrays.
18 * To get a value of any of them the caller must use device_property_read_u8_array().
16 */ 19 */
17 20
18#define pr_fmt(fmt) "apple-properties: " fmt 21#define pr_fmt(fmt) "apple-properties: " fmt
@@ -96,12 +99,13 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
96 entry[i].name = key; 99 entry[i].name = key;
97 entry[i].length = val_len - sizeof(val_len); 100 entry[i].length = val_len - sizeof(val_len);
98 entry[i].is_array = !!entry[i].length; 101 entry[i].is_array = !!entry[i].length;
99 entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len); 102 entry[i].type = DEV_PROP_U8;
103 entry[i].pointer.u8_data = ptr + key_len + sizeof(val_len);
100 104
101 if (dump_properties) { 105 if (dump_properties) {
102 dev_info(dev, "property: %s\n", entry[i].name); 106 dev_info(dev, "property: %s\n", entry[i].name);
103 print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET, 107 print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET,
104 16, 1, entry[i].pointer.raw_data, 108 16, 1, entry[i].pointer.u8_data,
105 entry[i].length, true); 109 entry[i].length, true);
106 } 110 }
107 111
diff --git a/include/linux/property.h b/include/linux/property.h
index 2eea4b310fc2..ac8a1ebc4c1b 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -178,7 +178,7 @@ static inline int fwnode_property_read_u64(const struct fwnode_handle *fwnode,
178 * @name: Name of the property. 178 * @name: Name of the property.
179 * @length: Length of data making up the value. 179 * @length: Length of data making up the value.
180 * @is_array: True when the property is an array. 180 * @is_array: True when the property is an array.
181 * @is_string: True when property is a string. 181 * @type: Type of the data in unions.
182 * @pointer: Pointer to the property (an array of items of the given type). 182 * @pointer: Pointer to the property (an array of items of the given type).
183 * @value: Value of the property (when it is a single item of the given type). 183 * @value: Value of the property (when it is a single item of the given type).
184 */ 184 */
@@ -186,10 +186,9 @@ struct property_entry {
186 const char *name; 186 const char *name;
187 size_t length; 187 size_t length;
188 bool is_array; 188 bool is_array;
189 bool is_string; 189 enum dev_prop_type type;
190 union { 190 union {
191 union { 191 union {
192 const void *raw_data;
193 const u8 *u8_data; 192 const u8 *u8_data;
194 const u16 *u16_data; 193 const u16 *u16_data;
195 const u32 *u32_data; 194 const u32 *u32_data;
@@ -197,7 +196,6 @@ struct property_entry {
197 const char * const *str; 196 const char * const *str;
198 } pointer; 197 } pointer;
199 union { 198 union {
200 unsigned long long raw_data;
201 u8 u8_data; 199 u8 u8_data;
202 u16 u16_data; 200 u16 u16_data;
203 u32 u32_data; 201 u32 u32_data;
@@ -213,55 +211,55 @@ struct property_entry {
213 * and structs. 211 * and structs.
214 */ 212 */
215 213
216#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _val_) \ 214#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _Type_, _val_) \
217(struct property_entry) { \ 215(struct property_entry) { \
218 .name = _name_, \ 216 .name = _name_, \
219 .length = ARRAY_SIZE(_val_) * sizeof(_type_), \ 217 .length = ARRAY_SIZE(_val_) * sizeof(_type_), \
220 .is_array = true, \ 218 .is_array = true, \
221 .is_string = false, \ 219 .type = DEV_PROP_##_Type_, \
222 { .pointer = { ._type_##_data = _val_ } }, \ 220 { .pointer = { ._type_##_data = _val_ } }, \
223} 221}
224 222
225#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \ 223#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \
226 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, _val_) 224 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, U8, _val_)
227#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_) \ 225#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_) \
228 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, _val_) 226 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, U16, _val_)
229#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_) \ 227#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_) \
230 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, _val_) 228 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, U32, _val_)
231#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_) \ 229#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_) \
232 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, _val_) 230 PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, U64, _val_)
233 231
234#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \ 232#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \
235(struct property_entry) { \ 233(struct property_entry) { \
236 .name = _name_, \ 234 .name = _name_, \
237 .length = ARRAY_SIZE(_val_) * sizeof(const char *), \ 235 .length = ARRAY_SIZE(_val_) * sizeof(const char *), \
238 .is_array = true, \ 236 .is_array = true, \
239 .is_string = true, \ 237 .type = DEV_PROP_STRING, \
240 { .pointer = { .str = _val_ } }, \ 238 { .pointer = { .str = _val_ } }, \
241} 239}
242 240
243#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _val_) \ 241#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _Type_, _val_) \
244(struct property_entry) { \ 242(struct property_entry) { \
245 .name = _name_, \ 243 .name = _name_, \
246 .length = sizeof(_type_), \ 244 .length = sizeof(_type_), \
247 .is_string = false, \ 245 .type = DEV_PROP_##_Type_, \
248 { .value = { ._type_##_data = _val_ } }, \ 246 { .value = { ._type_##_data = _val_ } }, \
249} 247}
250 248
251#define PROPERTY_ENTRY_U8(_name_, _val_) \ 249#define PROPERTY_ENTRY_U8(_name_, _val_) \
252 PROPERTY_ENTRY_INTEGER(_name_, u8, _val_) 250 PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_)
253#define PROPERTY_ENTRY_U16(_name_, _val_) \ 251#define PROPERTY_ENTRY_U16(_name_, _val_) \
254 PROPERTY_ENTRY_INTEGER(_name_, u16, _val_) 252 PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_)
255#define PROPERTY_ENTRY_U32(_name_, _val_) \ 253#define PROPERTY_ENTRY_U32(_name_, _val_) \
256 PROPERTY_ENTRY_INTEGER(_name_, u32, _val_) 254 PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_)
257#define PROPERTY_ENTRY_U64(_name_, _val_) \ 255#define PROPERTY_ENTRY_U64(_name_, _val_) \
258 PROPERTY_ENTRY_INTEGER(_name_, u64, _val_) 256 PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_)
259 257
260#define PROPERTY_ENTRY_STRING(_name_, _val_) \ 258#define PROPERTY_ENTRY_STRING(_name_, _val_) \
261(struct property_entry) { \ 259(struct property_entry) { \
262 .name = _name_, \ 260 .name = _name_, \
263 .length = sizeof(_val_), \ 261 .length = sizeof(_val_), \
264 .is_string = true, \ 262 .type = DEV_PROP_STRING, \
265 { .value = { .str = _val_ } }, \ 263 { .value = { .str = _val_ } }, \
266} 264}
267 265