diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 13:13:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 13:13:13 -0400 |
commit | a74e0c4c9cb02d44bc5ec1a70a6ba599366fb130 (patch) | |
tree | 5c55e103af8770a8b9dcfff48e8bac0074ecd083 | |
parent | f4fe74cc909bf811cd9cc7fd84f5a7514e06a7e1 (diff) | |
parent | 63dcc7090137a893322432e156d66be3ce104615 (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.c | 104 | ||||
-rw-r--r-- | drivers/firmware/efi/apple-properties.c | 8 | ||||
-rw-r--r-- | include/linux/property.h | 52 |
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 | ||
59 | static 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 | |||
87 | static 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 | |||
59 | static const void *pset_prop_find(const struct property_set *pset, | 125 | static 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 | ||
699 | static void property_entry_free_data(const struct property_entry *p) | 762 | static 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) | |||
716 | static int property_copy_string_array(struct property_entry *dst, | 780 | static 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 | ||
741 | static int property_entry_copy_data(struct property_entry *dst, | 805 | static 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 | ||