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 /drivers | |
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
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/property.c | 104 | ||||
-rw-r--r-- | drivers/firmware/efi/apple-properties.c | 8 |
2 files changed, 92 insertions, 20 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 | ||