aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/raspberrypi.c
diff options
context:
space:
mode:
authorJames Hughes <james.hughes@raspberrypi.org>2018-11-16 09:39:07 -0500
committerStefan Wahren <stefan.wahren@i2se.com>2018-11-18 06:26:43 -0500
commit91c6ada69f396e663acb2b713e8acb8a9463557d (patch)
treee5ddf73117ed05b65973da735f92abc0e507bb86 /drivers/firmware/raspberrypi.c
parentbb661b70883717154e194cad544e2b9c25895268 (diff)
firmware: raspberrypi: Fix firmware calls with large buffers
Commit a1547e0bca51 ("firmware: raspberrypi: Remove VLA usage") moved away from VLA's to a fixed maximum size for mailbox data. However, some mailbox calls use larger data buffers than the maximum allowed in that change. This fix therefor moves from using fixed buffers to kmalloc to ensure all sizes are catered for. There is some documentation, which is somewhat out of date, on the mailbox calls here : https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface Fixes: a1547e0bca51 ("firmware: raspberrypi: Remove VLA usage") Signed-off-by: James Hughes <james.hughes@raspberrypi.org> Reviewed-by: Eric Anholt <eric@anholt.net> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Diffstat (limited to 'drivers/firmware/raspberrypi.c')
-rw-r--r--drivers/firmware/raspberrypi.c35
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
26static struct platform_device *rpi_hwmon; 25static struct platform_device *rpi_hwmon;
27 26
28struct rpi_firmware { 27struct rpi_firmware {
@@ -148,28 +147,30 @@ EXPORT_SYMBOL_GPL(rpi_firmware_property_list);
148int rpi_firmware_property(struct rpi_firmware *fw, 147int 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}