diff options
Diffstat (limited to 'drivers/firmware/raspberrypi.c')
-rw-r--r-- | drivers/firmware/raspberrypi.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index bf45ac450954..d3f7d1434657 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/of_platform.h> | 15 | #include <linux/of_platform.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/slab.h> | ||
17 | #include <soc/bcm2835/raspberrypi-firmware.h> | 18 | #include <soc/bcm2835/raspberrypi-firmware.h> |
18 | 19 | ||
19 | #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) | 20 | #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) |
@@ -21,8 +22,6 @@ | |||
21 | #define MBOX_DATA28(msg) ((msg) & ~0xf) | 22 | #define MBOX_DATA28(msg) ((msg) & ~0xf) |
22 | #define MBOX_CHAN_PROPERTY 8 | 23 | #define MBOX_CHAN_PROPERTY 8 |
23 | 24 | ||
24 | #define MAX_RPI_FW_PROP_BUF_SIZE 32 | ||
25 | |||
26 | static struct platform_device *rpi_hwmon; | 25 | static struct platform_device *rpi_hwmon; |
27 | 26 | ||
28 | struct rpi_firmware { | 27 | struct rpi_firmware { |
@@ -148,28 +147,30 @@ EXPORT_SYMBOL_GPL(rpi_firmware_property_list); | |||
148 | int rpi_firmware_property(struct rpi_firmware *fw, | 147 | int rpi_firmware_property(struct rpi_firmware *fw, |
149 | u32 tag, void *tag_data, size_t buf_size) | 148 | u32 tag, void *tag_data, size_t buf_size) |
150 | { | 149 | { |
151 | /* Single tags are very small (generally 8 bytes), so the | 150 | struct rpi_firmware_property_tag_header *header; |
152 | * stack should be safe. | ||
153 | */ | ||
154 | u8 data[sizeof(struct rpi_firmware_property_tag_header) + | ||
155 | MAX_RPI_FW_PROP_BUF_SIZE]; | ||
156 | struct rpi_firmware_property_tag_header *header = | ||
157 | (struct rpi_firmware_property_tag_header *)data; | ||
158 | int ret; | 151 | int ret; |
159 | 152 | ||
160 | if (WARN_ON(buf_size > sizeof(data) - sizeof(*header))) | 153 | /* Some mailboxes can use over 1k bytes. Rather than checking |
161 | return -EINVAL; | 154 | * size and using stack or kmalloc depending on requirements, |
155 | * just use kmalloc. Mailboxes don't get called enough to worry | ||
156 | * too much about the time taken in the allocation. | ||
157 | */ | ||
158 | void *data = kmalloc(sizeof(*header) + buf_size, GFP_KERNEL); | ||
162 | 159 | ||
160 | if (!data) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | header = data; | ||
163 | header->tag = tag; | 164 | header->tag = tag; |
164 | header->buf_size = buf_size; | 165 | header->buf_size = buf_size; |
165 | header->req_resp_size = 0; | 166 | header->req_resp_size = 0; |
166 | memcpy(data + sizeof(struct rpi_firmware_property_tag_header), | 167 | memcpy(data + sizeof(*header), tag_data, buf_size); |
167 | tag_data, buf_size); | 168 | |
169 | ret = rpi_firmware_property_list(fw, data, buf_size + sizeof(*header)); | ||
170 | |||
171 | memcpy(tag_data, data + sizeof(*header), buf_size); | ||
168 | 172 | ||
169 | ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header)); | 173 | kfree(data); |
170 | memcpy(tag_data, | ||
171 | data + sizeof(struct rpi_firmware_property_tag_header), | ||
172 | buf_size); | ||
173 | 174 | ||
174 | return ret; | 175 | return ret; |
175 | } | 176 | } |