aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javier.martinez@collabora.co.uk>2015-06-09 07:04:42 -0400
committerLee Jones <lee.jones@linaro.org>2015-06-15 08:18:19 -0400
commita841178445bb72a3d566b4e6ab9d19e9b002eb47 (patch)
treebdc857e82c9c9e8b49bd5471efa5a954673d58f0 /drivers/platform
parentbb03ffb96c72418d06e75c7b74ea62e04c78d322 (diff)
mfd: cros_ec: Use a zero-length array for command data
Commit 1b84f2a4cd4a ("mfd: cros_ec: Use fixed size arrays to transfer data with the EC") modified the struct cros_ec_command fields to not use pointers for the input and output buffers and use fixed length arrays instead. This change was made because the cros_ec ioctl API uses that struct cros_ec_command to allow user-space to send commands to the EC and to get data from the EC. So using pointers made the API not 64-bit safe. Unfortunately this approach was not flexible enough for all the use-cases since there may be a need to send larger commands on newer versions of the EC command protocol. So to avoid to choose a constant length that it may be too big for most commands and thus wasting memory and CPU cycles on copy from and to user-space or having a size that is too small for some big commands, use a zero-length array that is both 64-bit safe and flexible. The same buffer is used for both output and input data so the maximum of these values should be used to allocate it. Suggested-by: Gwendal Grignou <gwendal@chromium.org> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/chrome/cros_ec_dev.c65
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c152
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c8
-rw-r--r--drivers/platform/chrome/cros_ec_sysfs.c154
4 files changed, 244 insertions, 135 deletions
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index 6090d0b2826f..e91ced1cb8ce 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -20,6 +20,7 @@
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/slab.h>
23#include <linux/uaccess.h> 24#include <linux/uaccess.h>
24 25
25#include "cros_ec_dev.h" 26#include "cros_ec_dev.h"
@@ -36,28 +37,31 @@ static int ec_get_version(struct cros_ec_device *ec, char *str, int maxlen)
36 static const char * const current_image_name[] = { 37 static const char * const current_image_name[] = {
37 "unknown", "read-only", "read-write", "invalid", 38 "unknown", "read-only", "read-write", "invalid",
38 }; 39 };
39 struct cros_ec_command msg = { 40 struct cros_ec_command *msg;
40 .version = 0,
41 .command = EC_CMD_GET_VERSION,
42 .outdata = { 0 },
43 .outsize = 0,
44 .indata = { 0 },
45 .insize = sizeof(*resp),
46 };
47 int ret; 41 int ret;
48 42
49 ret = cros_ec_cmd_xfer(ec, &msg); 43 msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
44 if (!msg)
45 return -ENOMEM;
46
47 msg->version = 0;
48 msg->command = EC_CMD_GET_VERSION;
49 msg->insize = sizeof(*resp);
50 msg->outsize = 0;
51
52 ret = cros_ec_cmd_xfer(ec, msg);
50 if (ret < 0) 53 if (ret < 0)
51 return ret; 54 goto exit;
52 55
53 if (msg.result != EC_RES_SUCCESS) { 56 if (msg->result != EC_RES_SUCCESS) {
54 snprintf(str, maxlen, 57 snprintf(str, maxlen,
55 "%s\nUnknown EC version: EC returned %d\n", 58 "%s\nUnknown EC version: EC returned %d\n",
56 CROS_EC_DEV_VERSION, msg.result); 59 CROS_EC_DEV_VERSION, msg->result);
57 return 0; 60 ret = -EINVAL;
61 goto exit;
58 } 62 }
59 63
60 resp = (struct ec_response_get_version *)msg.indata; 64 resp = (struct ec_response_get_version *)msg->data;
61 if (resp->current_image >= ARRAY_SIZE(current_image_name)) 65 if (resp->current_image >= ARRAY_SIZE(current_image_name))
62 resp->current_image = 3; /* invalid */ 66 resp->current_image = 3; /* invalid */
63 67
@@ -65,7 +69,10 @@ static int ec_get_version(struct cros_ec_device *ec, char *str, int maxlen)
65 resp->version_string_ro, resp->version_string_rw, 69 resp->version_string_ro, resp->version_string_rw,
66 current_image_name[resp->current_image]); 70 current_image_name[resp->current_image]);
67 71
68 return 0; 72 ret = 0;
73exit:
74 kfree(msg);
75 return ret;
69} 76}
70 77
71/* Device file ops */ 78/* Device file ops */
@@ -110,20 +117,32 @@ static ssize_t ec_device_read(struct file *filp, char __user *buffer,
110static long ec_device_ioctl_xcmd(struct cros_ec_device *ec, void __user *arg) 117static long ec_device_ioctl_xcmd(struct cros_ec_device *ec, void __user *arg)
111{ 118{
112 long ret; 119 long ret;
113 struct cros_ec_command s_cmd = { }; 120 struct cros_ec_command u_cmd;
121 struct cros_ec_command *s_cmd;
114 122
115 if (copy_from_user(&s_cmd, arg, sizeof(s_cmd))) 123 if (copy_from_user(&u_cmd, arg, sizeof(u_cmd)))
116 return -EFAULT; 124 return -EFAULT;
117 125
118 ret = cros_ec_cmd_xfer(ec, &s_cmd); 126 s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
127 GFP_KERNEL);
128 if (!s_cmd)
129 return -ENOMEM;
130
131 if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) {
132 ret = -EFAULT;
133 goto exit;
134 }
135
136 ret = cros_ec_cmd_xfer(ec, s_cmd);
119 /* Only copy data to userland if data was received. */ 137 /* Only copy data to userland if data was received. */
120 if (ret < 0) 138 if (ret < 0)
121 return ret; 139 goto exit;
122 140
123 if (copy_to_user(arg, &s_cmd, sizeof(s_cmd))) 141 if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + u_cmd.insize))
124 return -EFAULT; 142 ret = -EFAULT;
125 143exit:
126 return 0; 144 kfree(s_cmd);
145 return ret;
127} 146}
128 147
129static long ec_device_ioctl_readmem(struct cros_ec_device *ec, void __user *arg) 148static long ec_device_ioctl_readmem(struct cros_ec_device *ec, void __user *arg)
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index b4ff47a9069a..560e5d41b7ae 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -31,6 +31,7 @@
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/uaccess.h> 33#include <linux/uaccess.h>
34#include <linux/slab.h>
34 35
35#include "cros_ec_dev.h" 36#include "cros_ec_dev.h"
36 37
@@ -91,54 +92,79 @@ out:
91 return ret; 92 return ret;
92} 93}
93 94
94#define INIT_MSG(P, R) { \ 95static struct cros_ec_command *alloc_lightbar_cmd_msg(void)
95 .command = EC_CMD_LIGHTBAR_CMD, \ 96{
96 .outsize = sizeof(*P), \ 97 struct cros_ec_command *msg;
97 .insize = sizeof(*R), \ 98 int len;
98 } 99
100 len = max(sizeof(struct ec_params_lightbar),
101 sizeof(struct ec_response_lightbar));
102
103 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL);
104 if (!msg)
105 return NULL;
106
107 msg->version = 0;
108 msg->command = EC_CMD_LIGHTBAR_CMD;
109 msg->outsize = sizeof(struct ec_params_lightbar);
110 msg->insize = sizeof(struct ec_response_lightbar);
111
112 return msg;
113}
99 114
100static int get_lightbar_version(struct cros_ec_device *ec, 115static int get_lightbar_version(struct cros_ec_device *ec,
101 uint32_t *ver_ptr, uint32_t *flg_ptr) 116 uint32_t *ver_ptr, uint32_t *flg_ptr)
102{ 117{
103 struct ec_params_lightbar *param; 118 struct ec_params_lightbar *param;
104 struct ec_response_lightbar *resp; 119 struct ec_response_lightbar *resp;
105 struct cros_ec_command msg = INIT_MSG(param, resp); 120 struct cros_ec_command *msg;
106 int ret; 121 int ret;
107 122
108 param = (struct ec_params_lightbar *)msg.outdata; 123 msg = alloc_lightbar_cmd_msg();
109 param->cmd = LIGHTBAR_CMD_VERSION; 124 if (!msg)
110 ret = cros_ec_cmd_xfer(ec, &msg);
111 if (ret < 0)
112 return 0; 125 return 0;
113 126
114 switch (msg.result) { 127 param = (struct ec_params_lightbar *)msg->data;
128 param->cmd = LIGHTBAR_CMD_VERSION;
129 ret = cros_ec_cmd_xfer(ec, msg);
130 if (ret < 0) {
131 ret = 0;
132 goto exit;
133 }
134
135 switch (msg->result) {
115 case EC_RES_INVALID_PARAM: 136 case EC_RES_INVALID_PARAM:
116 /* Pixel had no version command. */ 137 /* Pixel had no version command. */
117 if (ver_ptr) 138 if (ver_ptr)
118 *ver_ptr = 0; 139 *ver_ptr = 0;
119 if (flg_ptr) 140 if (flg_ptr)
120 *flg_ptr = 0; 141 *flg_ptr = 0;
121 return 1; 142 ret = 1;
143 goto exit;
122 144
123 case EC_RES_SUCCESS: 145 case EC_RES_SUCCESS:
124 resp = (struct ec_response_lightbar *)msg.indata; 146 resp = (struct ec_response_lightbar *)msg->data;
125 147
126 /* Future devices w/lightbars should implement this command */ 148 /* Future devices w/lightbars should implement this command */
127 if (ver_ptr) 149 if (ver_ptr)
128 *ver_ptr = resp->version.num; 150 *ver_ptr = resp->version.num;
129 if (flg_ptr) 151 if (flg_ptr)
130 *flg_ptr = resp->version.flags; 152 *flg_ptr = resp->version.flags;
131 return 1; 153 ret = 1;
154 goto exit;
132 } 155 }
133 156
134 /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */ 157 /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */
135 return 0; 158 ret = 0;
159exit:
160 kfree(msg);
161 return ret;
136} 162}
137 163
138static ssize_t version_show(struct device *dev, 164static ssize_t version_show(struct device *dev,
139 struct device_attribute *attr, char *buf) 165 struct device_attribute *attr, char *buf)
140{ 166{
141 uint32_t version, flags; 167 uint32_t version = 0, flags = 0;
142 struct cros_ec_device *ec = dev_get_drvdata(dev); 168 struct cros_ec_device *ec = dev_get_drvdata(dev);
143 int ret; 169 int ret;
144 170
@@ -158,8 +184,7 @@ static ssize_t brightness_store(struct device *dev,
158 const char *buf, size_t count) 184 const char *buf, size_t count)
159{ 185{
160 struct ec_params_lightbar *param; 186 struct ec_params_lightbar *param;
161 struct ec_response_lightbar *resp; 187 struct cros_ec_command *msg;
162 struct cros_ec_command msg = INIT_MSG(param, resp);
163 int ret; 188 int ret;
164 unsigned int val; 189 unsigned int val;
165 struct cros_ec_device *ec = dev_get_drvdata(dev); 190 struct cros_ec_device *ec = dev_get_drvdata(dev);
@@ -167,21 +192,30 @@ static ssize_t brightness_store(struct device *dev,
167 if (kstrtouint(buf, 0, &val)) 192 if (kstrtouint(buf, 0, &val))
168 return -EINVAL; 193 return -EINVAL;
169 194
170 param = (struct ec_params_lightbar *)msg.outdata; 195 msg = alloc_lightbar_cmd_msg();
196 if (!msg)
197 return -ENOMEM;
198
199 param = (struct ec_params_lightbar *)msg->data;
171 param->cmd = LIGHTBAR_CMD_BRIGHTNESS; 200 param->cmd = LIGHTBAR_CMD_BRIGHTNESS;
172 param->brightness.num = val; 201 param->brightness.num = val;
173 ret = lb_throttle(); 202 ret = lb_throttle();
174 if (ret) 203 if (ret)
175 return ret; 204 goto exit;
176 205
177 ret = cros_ec_cmd_xfer(ec, &msg); 206 ret = cros_ec_cmd_xfer(ec, msg);
178 if (ret < 0) 207 if (ret < 0)
179 return ret; 208 goto exit;
180 209
181 if (msg.result != EC_RES_SUCCESS) 210 if (msg->result != EC_RES_SUCCESS) {
182 return -EINVAL; 211 ret = -EINVAL;
212 goto exit;
213 }
183 214
184 return count; 215 ret = count;
216exit:
217 kfree(msg);
218 return ret;
185} 219}
186 220
187 221
@@ -196,12 +230,15 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
196 const char *buf, size_t count) 230 const char *buf, size_t count)
197{ 231{
198 struct ec_params_lightbar *param; 232 struct ec_params_lightbar *param;
199 struct ec_response_lightbar *resp; 233 struct cros_ec_command *msg;
200 struct cros_ec_command msg = INIT_MSG(param, resp);
201 struct cros_ec_device *ec = dev_get_drvdata(dev); 234 struct cros_ec_device *ec = dev_get_drvdata(dev);
202 unsigned int val[4]; 235 unsigned int val[4];
203 int ret, i = 0, j = 0, ok = 0; 236 int ret, i = 0, j = 0, ok = 0;
204 237
238 msg = alloc_lightbar_cmd_msg();
239 if (!msg)
240 return -ENOMEM;
241
205 do { 242 do {
206 /* Skip any whitespace */ 243 /* Skip any whitespace */
207 while (*buf && isspace(*buf)) 244 while (*buf && isspace(*buf))
@@ -215,7 +252,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
215 return -EINVAL; 252 return -EINVAL;
216 253
217 if (i == 4) { 254 if (i == 4) {
218 param = (struct ec_params_lightbar *)msg.outdata; 255 param = (struct ec_params_lightbar *)msg->data;
219 param->cmd = LIGHTBAR_CMD_RGB; 256 param->cmd = LIGHTBAR_CMD_RGB;
220 param->rgb.led = val[0]; 257 param->rgb.led = val[0];
221 param->rgb.red = val[1]; 258 param->rgb.red = val[1];
@@ -231,12 +268,14 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
231 return ret; 268 return ret;
232 } 269 }
233 270
234 ret = cros_ec_cmd_xfer(ec, &msg); 271 ret = cros_ec_cmd_xfer(ec, msg);
235 if (ret < 0) 272 if (ret < 0)
236 return ret; 273 goto exit;
237 274
238 if (msg.result != EC_RES_SUCCESS) 275 if (msg->result != EC_RES_SUCCESS) {
239 return -EINVAL; 276 ret = -EINVAL;
277 goto exit;
278 }
240 279
241 i = 0; 280 i = 0;
242 ok = 1; 281 ok = 1;
@@ -248,6 +287,8 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
248 287
249 } while (*buf); 288 } while (*buf);
250 289
290exit:
291 kfree(msg);
251 return (ok && i == 0) ? count : -EINVAL; 292 return (ok && i == 0) ? count : -EINVAL;
252} 293}
253 294
@@ -261,42 +302,55 @@ static ssize_t sequence_show(struct device *dev,
261{ 302{
262 struct ec_params_lightbar *param; 303 struct ec_params_lightbar *param;
263 struct ec_response_lightbar *resp; 304 struct ec_response_lightbar *resp;
264 struct cros_ec_command msg = INIT_MSG(param, resp); 305 struct cros_ec_command *msg;
265 int ret; 306 int ret;
266 struct cros_ec_device *ec = dev_get_drvdata(dev); 307 struct cros_ec_device *ec = dev_get_drvdata(dev);
267 308
268 param = (struct ec_params_lightbar *)msg.outdata; 309 msg = alloc_lightbar_cmd_msg();
310 if (!msg)
311 return -ENOMEM;
312
313 param = (struct ec_params_lightbar *)msg->data;
269 param->cmd = LIGHTBAR_CMD_GET_SEQ; 314 param->cmd = LIGHTBAR_CMD_GET_SEQ;
270 ret = lb_throttle(); 315 ret = lb_throttle();
271 if (ret) 316 if (ret)
272 return ret; 317 goto exit;
273 318
274 ret = cros_ec_cmd_xfer(ec, &msg); 319 ret = cros_ec_cmd_xfer(ec, msg);
275 if (ret < 0) 320 if (ret < 0)
276 return ret; 321 goto exit;
277 322
278 if (msg.result != EC_RES_SUCCESS) 323 if (msg->result != EC_RES_SUCCESS) {
279 return scnprintf(buf, PAGE_SIZE, 324 ret = scnprintf(buf, PAGE_SIZE,
280 "ERROR: EC returned %d\n", msg.result); 325 "ERROR: EC returned %d\n", msg->result);
326 goto exit;
327 }
281 328
282 resp = (struct ec_response_lightbar *)msg.indata; 329 resp = (struct ec_response_lightbar *)msg->data;
283 if (resp->get_seq.num >= ARRAY_SIZE(seqname)) 330 if (resp->get_seq.num >= ARRAY_SIZE(seqname))
284 return scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num); 331 ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num);
285 else 332 else
286 return scnprintf(buf, PAGE_SIZE, "%s\n", 333 ret = scnprintf(buf, PAGE_SIZE, "%s\n",
287 seqname[resp->get_seq.num]); 334 seqname[resp->get_seq.num]);
335
336exit:
337 kfree(msg);
338 return ret;
288} 339}
289 340
290static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, 341static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
291 const char *buf, size_t count) 342 const char *buf, size_t count)
292{ 343{
293 struct ec_params_lightbar *param; 344 struct ec_params_lightbar *param;
294 struct ec_response_lightbar *resp; 345 struct cros_ec_command *msg;
295 struct cros_ec_command msg = INIT_MSG(param, resp);
296 unsigned int num; 346 unsigned int num;
297 int ret, len; 347 int ret, len;
298 struct cros_ec_device *ec = dev_get_drvdata(dev); 348 struct cros_ec_device *ec = dev_get_drvdata(dev);
299 349
350 msg = alloc_lightbar_cmd_msg();
351 if (!msg)
352 return -ENOMEM;
353
300 for (len = 0; len < count; len++) 354 for (len = 0; len < count; len++)
301 if (!isalnum(buf[len])) 355 if (!isalnum(buf[len]))
302 break; 356 break;
@@ -311,18 +365,18 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
311 return ret; 365 return ret;
312 } 366 }
313 367
314 param = (struct ec_params_lightbar *)msg.outdata; 368 param = (struct ec_params_lightbar *)msg->data;
315 param->cmd = LIGHTBAR_CMD_SEQ; 369 param->cmd = LIGHTBAR_CMD_SEQ;
316 param->seq.num = num; 370 param->seq.num = num;
317 ret = lb_throttle(); 371 ret = lb_throttle();
318 if (ret) 372 if (ret)
319 return ret; 373 return ret;
320 374
321 ret = cros_ec_cmd_xfer(ec, &msg); 375 ret = cros_ec_cmd_xfer(ec, msg);
322 if (ret < 0) 376 if (ret < 0)
323 return ret; 377 return ret;
324 378
325 if (msg.result != EC_RES_SUCCESS) 379 if (msg->result != EC_RES_SUCCESS)
326 return -EINVAL; 380 return -EINVAL;
327 381
328 return count; 382 return count;
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index 860310513cf0..4c7f0df33bf8 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -73,8 +73,8 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
73 73
74 /* Copy data and update checksum */ 74 /* Copy data and update checksum */
75 for (i = 0; i < msg->outsize; i++) { 75 for (i = 0; i < msg->outsize; i++) {
76 outb(msg->outdata[i], EC_LPC_ADDR_HOST_PARAM + i); 76 outb(msg->data[i], EC_LPC_ADDR_HOST_PARAM + i);
77 csum += msg->outdata[i]; 77 csum += msg->data[i];
78 } 78 }
79 79
80 /* Finalize checksum and write args */ 80 /* Finalize checksum and write args */
@@ -129,8 +129,8 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
129 129
130 /* Read response and update checksum */ 130 /* Read response and update checksum */
131 for (i = 0; i < args.data_size; i++) { 131 for (i = 0; i < args.data_size; i++) {
132 msg->indata[i] = inb(EC_LPC_ADDR_HOST_PARAM + i); 132 msg->data[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
133 csum += msg->indata[i]; 133 csum += msg->data[i];
134 } 134 }
135 135
136 /* Verify checksum */ 136 /* Verify checksum */
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c
index fb62ab6cc659..78ba82d670cb 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -29,6 +29,7 @@
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/printk.h> 31#include <linux/printk.h>
32#include <linux/slab.h>
32#include <linux/stat.h> 33#include <linux/stat.h>
33#include <linux/types.h> 34#include <linux/types.h>
34#include <linux/uaccess.h> 35#include <linux/uaccess.h>
@@ -66,14 +67,19 @@ static ssize_t store_ec_reboot(struct device *dev,
66 {"hibernate", EC_REBOOT_HIBERNATE, 0}, 67 {"hibernate", EC_REBOOT_HIBERNATE, 0},
67 {"at-shutdown", -1, EC_REBOOT_FLAG_ON_AP_SHUTDOWN}, 68 {"at-shutdown", -1, EC_REBOOT_FLAG_ON_AP_SHUTDOWN},
68 }; 69 };
69 struct cros_ec_command msg = { 0 }; 70 struct cros_ec_command *msg;
70 struct ec_params_reboot_ec *param = 71 struct ec_params_reboot_ec *param;
71 (struct ec_params_reboot_ec *)msg.outdata;
72 int got_cmd = 0, offset = 0; 72 int got_cmd = 0, offset = 0;
73 int i; 73 int i;
74 int ret; 74 int ret;
75 struct cros_ec_device *ec = dev_get_drvdata(dev); 75 struct cros_ec_device *ec = dev_get_drvdata(dev);
76 76
77 msg = kmalloc(sizeof(*msg) + sizeof(*param), GFP_KERNEL);
78 if (!msg)
79 return -ENOMEM;
80
81 param = (struct ec_params_reboot_ec *)msg->data;
82
77 param->flags = 0; 83 param->flags = 0;
78 while (1) { 84 while (1) {
79 /* Find word to start scanning */ 85 /* Find word to start scanning */
@@ -100,19 +106,26 @@ static ssize_t store_ec_reboot(struct device *dev,
100 offset++; 106 offset++;
101 } 107 }
102 108
103 if (!got_cmd) 109 if (!got_cmd) {
104 return -EINVAL; 110 count = -EINVAL;
105 111 goto exit;
106 msg.command = EC_CMD_REBOOT_EC;
107 msg.outsize = sizeof(param);
108 ret = cros_ec_cmd_xfer(ec, &msg);
109 if (ret < 0)
110 return ret;
111 if (msg.result != EC_RES_SUCCESS) {
112 dev_dbg(ec->dev, "EC result %d\n", msg.result);
113 return -EINVAL;
114 } 112 }
115 113
114 msg->version = 0;
115 msg->command = EC_CMD_REBOOT_EC;
116 msg->outsize = sizeof(*param);
117 msg->insize = 0;
118 ret = cros_ec_cmd_xfer(ec, msg);
119 if (ret < 0) {
120 count = ret;
121 goto exit;
122 }
123 if (msg->result != EC_RES_SUCCESS) {
124 dev_dbg(ec->dev, "EC result %d\n", msg->result);
125 count = -EINVAL;
126 }
127exit:
128 kfree(msg);
116 return count; 129 return count;
117} 130}
118 131
@@ -123,22 +136,32 @@ static ssize_t show_ec_version(struct device *dev,
123 struct ec_response_get_version *r_ver; 136 struct ec_response_get_version *r_ver;
124 struct ec_response_get_chip_info *r_chip; 137 struct ec_response_get_chip_info *r_chip;
125 struct ec_response_board_version *r_board; 138 struct ec_response_board_version *r_board;
126 struct cros_ec_command msg = { 0 }; 139 struct cros_ec_command *msg;
127 int ret; 140 int ret;
128 int count = 0; 141 int count = 0;
129 struct cros_ec_device *ec = dev_get_drvdata(dev); 142 struct cros_ec_device *ec = dev_get_drvdata(dev);
130 143
144 msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
145 if (!msg)
146 return -ENOMEM;
147
131 /* Get versions. RW may change. */ 148 /* Get versions. RW may change. */
132 msg.command = EC_CMD_GET_VERSION; 149 msg->version = 0;
133 msg.insize = sizeof(*r_ver); 150 msg->command = EC_CMD_GET_VERSION;
134 ret = cros_ec_cmd_xfer(ec, &msg); 151 msg->insize = sizeof(*r_ver);
135 if (ret < 0) 152 msg->outsize = 0;
136 return ret; 153 ret = cros_ec_cmd_xfer(ec, msg);
137 if (msg.result != EC_RES_SUCCESS) 154 if (ret < 0) {
138 return scnprintf(buf, PAGE_SIZE, 155 count = ret;
139 "ERROR: EC returned %d\n", msg.result); 156 goto exit;
157 }
158 if (msg->result != EC_RES_SUCCESS) {
159 count = scnprintf(buf, PAGE_SIZE,
160 "ERROR: EC returned %d\n", msg->result);
161 goto exit;
162 }
140 163
141 r_ver = (struct ec_response_get_version *)msg.indata; 164 r_ver = (struct ec_response_get_version *)msg->data;
142 /* Strings should be null-terminated, but let's be sure. */ 165 /* Strings should be null-terminated, but let's be sure. */
143 r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0'; 166 r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0';
144 r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0'; 167 r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0';
@@ -152,33 +175,33 @@ static ssize_t show_ec_version(struct device *dev,
152 image_names[r_ver->current_image] : "?")); 175 image_names[r_ver->current_image] : "?"));
153 176
154 /* Get build info. */ 177 /* Get build info. */
155 msg.command = EC_CMD_GET_BUILD_INFO; 178 msg->command = EC_CMD_GET_BUILD_INFO;
156 msg.insize = sizeof(msg.indata); 179 msg->insize = EC_HOST_PARAM_SIZE;
157 ret = cros_ec_cmd_xfer(ec, &msg); 180 ret = cros_ec_cmd_xfer(ec, msg);
158 if (ret < 0) 181 if (ret < 0)
159 count += scnprintf(buf + count, PAGE_SIZE - count, 182 count += scnprintf(buf + count, PAGE_SIZE - count,
160 "Build info: XFER ERROR %d\n", ret); 183 "Build info: XFER ERROR %d\n", ret);
161 else if (msg.result != EC_RES_SUCCESS) 184 else if (msg->result != EC_RES_SUCCESS)
162 count += scnprintf(buf + count, PAGE_SIZE - count, 185 count += scnprintf(buf + count, PAGE_SIZE - count,
163 "Build info: EC error %d\n", msg.result); 186 "Build info: EC error %d\n", msg->result);
164 else { 187 else {
165 msg.indata[sizeof(msg.indata) - 1] = '\0'; 188 msg->data[sizeof(msg->data) - 1] = '\0';
166 count += scnprintf(buf + count, PAGE_SIZE - count, 189 count += scnprintf(buf + count, PAGE_SIZE - count,
167 "Build info: %s\n", msg.indata); 190 "Build info: %s\n", msg->data);
168 } 191 }
169 192
170 /* Get chip info. */ 193 /* Get chip info. */
171 msg.command = EC_CMD_GET_CHIP_INFO; 194 msg->command = EC_CMD_GET_CHIP_INFO;
172 msg.insize = sizeof(*r_chip); 195 msg->insize = sizeof(*r_chip);
173 ret = cros_ec_cmd_xfer(ec, &msg); 196 ret = cros_ec_cmd_xfer(ec, msg);
174 if (ret < 0) 197 if (ret < 0)
175 count += scnprintf(buf + count, PAGE_SIZE - count, 198 count += scnprintf(buf + count, PAGE_SIZE - count,
176 "Chip info: XFER ERROR %d\n", ret); 199 "Chip info: XFER ERROR %d\n", ret);
177 else if (msg.result != EC_RES_SUCCESS) 200 else if (msg->result != EC_RES_SUCCESS)
178 count += scnprintf(buf + count, PAGE_SIZE - count, 201 count += scnprintf(buf + count, PAGE_SIZE - count,
179 "Chip info: EC error %d\n", msg.result); 202 "Chip info: EC error %d\n", msg->result);
180 else { 203 else {
181 r_chip = (struct ec_response_get_chip_info *)msg.indata; 204 r_chip = (struct ec_response_get_chip_info *)msg->data;
182 205
183 r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0'; 206 r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0';
184 r_chip->name[sizeof(r_chip->name) - 1] = '\0'; 207 r_chip->name[sizeof(r_chip->name) - 1] = '\0';
@@ -192,23 +215,25 @@ static ssize_t show_ec_version(struct device *dev,
192 } 215 }
193 216
194 /* Get board version */ 217 /* Get board version */
195 msg.command = EC_CMD_GET_BOARD_VERSION; 218 msg->command = EC_CMD_GET_BOARD_VERSION;
196 msg.insize = sizeof(*r_board); 219 msg->insize = sizeof(*r_board);
197 ret = cros_ec_cmd_xfer(ec, &msg); 220 ret = cros_ec_cmd_xfer(ec, msg);
198 if (ret < 0) 221 if (ret < 0)
199 count += scnprintf(buf + count, PAGE_SIZE - count, 222 count += scnprintf(buf + count, PAGE_SIZE - count,
200 "Board version: XFER ERROR %d\n", ret); 223 "Board version: XFER ERROR %d\n", ret);
201 else if (msg.result != EC_RES_SUCCESS) 224 else if (msg->result != EC_RES_SUCCESS)
202 count += scnprintf(buf + count, PAGE_SIZE - count, 225 count += scnprintf(buf + count, PAGE_SIZE - count,
203 "Board version: EC error %d\n", msg.result); 226 "Board version: EC error %d\n", msg->result);
204 else { 227 else {
205 r_board = (struct ec_response_board_version *)msg.indata; 228 r_board = (struct ec_response_board_version *)msg->data;
206 229
207 count += scnprintf(buf + count, PAGE_SIZE - count, 230 count += scnprintf(buf + count, PAGE_SIZE - count,
208 "Board version: %d\n", 231 "Board version: %d\n",
209 r_board->board_version); 232 r_board->board_version);
210 } 233 }
211 234
235exit:
236 kfree(msg);
212 return count; 237 return count;
213} 238}
214 239
@@ -216,27 +241,38 @@ static ssize_t show_ec_flashinfo(struct device *dev,
216 struct device_attribute *attr, char *buf) 241 struct device_attribute *attr, char *buf)
217{ 242{
218 struct ec_response_flash_info *resp; 243 struct ec_response_flash_info *resp;
219 struct cros_ec_command msg = { 0 }; 244 struct cros_ec_command *msg;
220 int ret; 245 int ret;
221 struct cros_ec_device *ec = dev_get_drvdata(dev); 246 struct cros_ec_device *ec = dev_get_drvdata(dev);
222 247
248 msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
249 if (!msg)
250 return -ENOMEM;
251
223 /* The flash info shouldn't ever change, but ask each time anyway. */ 252 /* The flash info shouldn't ever change, but ask each time anyway. */
224 msg.command = EC_CMD_FLASH_INFO; 253 msg->version = 0;
225 msg.insize = sizeof(*resp); 254 msg->command = EC_CMD_FLASH_INFO;
226 ret = cros_ec_cmd_xfer(ec, &msg); 255 msg->insize = sizeof(*resp);
256 msg->outsize = 0;
257 ret = cros_ec_cmd_xfer(ec, msg);
227 if (ret < 0) 258 if (ret < 0)
228 return ret; 259 goto exit;
229 if (msg.result != EC_RES_SUCCESS) 260 if (msg->result != EC_RES_SUCCESS) {
230 return scnprintf(buf, PAGE_SIZE, 261 ret = scnprintf(buf, PAGE_SIZE,
231 "ERROR: EC returned %d\n", msg.result); 262 "ERROR: EC returned %d\n", msg->result);
232 263 goto exit;
233 resp = (struct ec_response_flash_info *)msg.indata; 264 }
234 265
235 return scnprintf(buf, PAGE_SIZE, 266 resp = (struct ec_response_flash_info *)msg->data;
236 "FlashSize %d\nWriteSize %d\n" 267
237 "EraseSize %d\nProtectSize %d\n", 268 ret = scnprintf(buf, PAGE_SIZE,
238 resp->flash_size, resp->write_block_size, 269 "FlashSize %d\nWriteSize %d\n"
239 resp->erase_block_size, resp->protect_block_size); 270 "EraseSize %d\nProtectSize %d\n",
271 resp->flash_size, resp->write_block_size,
272 resp->erase_block_size, resp->protect_block_size);
273exit:
274 kfree(msg);
275 return ret;
240} 276}
241 277
242/* Module initialization */ 278/* Module initialization */