aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-04-19 15:01:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-19 16:38:38 -0400
commitfcb136e1ac5774909e0d85189f721b8dfa800e0f (patch)
treeac89a706d67783063d4f752c3acddc04c5ab10e8 /drivers/misc/mei
parent6e0f180fd8b47fa0884177a142e41a86117edc23 (diff)
mei: fix reading large reposnes
While writting to device is limitted to max_msg_length advertized in client properites the read can be much longer delivered consequiting chunks. We use krealloc to enlarge the buffer when needed. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r--drivers/misc/mei/bus.c8
-rw-r--r--drivers/misc/mei/client.c7
-rw-r--r--drivers/misc/mei/client.h2
-rw-r--r--drivers/misc/mei/interrupt.c18
-rw-r--r--drivers/misc/mei/main.c7
5 files changed, 27 insertions, 15 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 834ceeb69cbf..1e935eacaa7f 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -286,7 +286,7 @@ int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
286 mutex_lock(&dev->device_lock); 286 mutex_lock(&dev->device_lock);
287 287
288 if (!cl->read_cb) { 288 if (!cl->read_cb) {
289 err = mei_cl_read_start(cl); 289 err = mei_cl_read_start(cl, length);
290 if (err < 0) { 290 if (err < 0) {
291 mutex_unlock(&dev->device_lock); 291 mutex_unlock(&dev->device_lock);
292 return err; 292 return err;
@@ -378,7 +378,7 @@ static void mei_bus_event_work(struct work_struct *work)
378 device->events = 0; 378 device->events = 0;
379 379
380 /* Prepare for the next read */ 380 /* Prepare for the next read */
381 mei_cl_read_start(device->cl); 381 mei_cl_read_start(device->cl, 0);
382} 382}
383 383
384int mei_cl_register_event_cb(struct mei_cl_device *device, 384int mei_cl_register_event_cb(struct mei_cl_device *device,
@@ -392,7 +392,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *device,
392 device->event_context = context; 392 device->event_context = context;
393 INIT_WORK(&device->event_work, mei_bus_event_work); 393 INIT_WORK(&device->event_work, mei_bus_event_work);
394 394
395 mei_cl_read_start(device->cl); 395 mei_cl_read_start(device->cl, 0);
396 396
397 return 0; 397 return 0;
398} 398}
@@ -436,7 +436,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
436 mutex_unlock(&dev->device_lock); 436 mutex_unlock(&dev->device_lock);
437 437
438 if (device->event_cb && !cl->read_cb) 438 if (device->event_cb && !cl->read_cb)
439 mei_cl_read_start(device->cl); 439 mei_cl_read_start(device->cl, 0);
440 440
441 if (!device->ops || !device->ops->enable) 441 if (!device->ops || !device->ops->enable)
442 return 0; 442 return 0;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 9541aa90d8f7..71892745e2e8 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -624,7 +624,7 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
624 * 624 *
625 * returns 0 on success, <0 on failure. 625 * returns 0 on success, <0 on failure.
626 */ 626 */
627int mei_cl_read_start(struct mei_cl *cl) 627int mei_cl_read_start(struct mei_cl *cl, size_t length)
628{ 628{
629 struct mei_device *dev; 629 struct mei_device *dev;
630 struct mei_cl_cb *cb; 630 struct mei_cl_cb *cb;
@@ -657,8 +657,9 @@ int mei_cl_read_start(struct mei_cl *cl)
657 if (!cb) 657 if (!cb)
658 return -ENOMEM; 658 return -ENOMEM;
659 659
660 rets = mei_io_cb_alloc_resp_buf(cb, 660 /* always allocate at least client max message */
661 dev->me_clients[i].props.max_msg_length); 661 length = max_t(size_t, length, dev->me_clients[i].props.max_msg_length);
662 rets = mei_io_cb_alloc_resp_buf(cb, length);
662 if (rets) 663 if (rets)
663 goto err; 664 goto err;
664 665
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index e890c8bf89d0..cfdb144526aa 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -87,7 +87,7 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
87bool mei_cl_is_other_connecting(struct mei_cl *cl); 87bool mei_cl_is_other_connecting(struct mei_cl *cl);
88int mei_cl_disconnect(struct mei_cl *cl); 88int mei_cl_disconnect(struct mei_cl *cl);
89int mei_cl_connect(struct mei_cl *cl, struct file *file); 89int mei_cl_connect(struct mei_cl *cl, struct file *file);
90int mei_cl_read_start(struct mei_cl *cl); 90int mei_cl_read_start(struct mei_cl *cl, size_t length);
91int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); 91int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
92 92
93void mei_host_client_init(struct work_struct *work); 93void mei_host_client_init(struct work_struct *work);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 9bf64c06fa39..74730713a8d3 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -145,9 +145,21 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
145 } 145 }
146 146
147 if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) { 147 if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
148 dev_warn(&dev->pdev->dev, "message overflow.\n"); 148 dev_dbg(&dev->pdev->dev, "message overflow. size %d len %d idx %ld\n",
149 list_del(&cb->list); 149 cb->response_buffer.size,
150 return -ENOMEM; 150 mei_hdr->length, cb->buf_idx);
151 cb->response_buffer.data =
152 krealloc(cb->response_buffer.data,
153 mei_hdr->length + cb->buf_idx,
154 GFP_KERNEL);
155
156 if (!cb->response_buffer.data) {
157 dev_err(&dev->pdev->dev, "allocation failed.\n");
158 list_del(&cb->list);
159 return -ENOMEM;
160 }
161 cb->response_buffer.size =
162 mei_hdr->length + cb->buf_idx;
151 } 163 }
152 164
153 buffer = cb->response_buffer.data + cb->buf_idx; 165 buffer = cb->response_buffer.data + cb->buf_idx;
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 78b4da5ed96c..7c44c8dbae42 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -244,7 +244,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
244 goto out; 244 goto out;
245 } 245 }
246 246
247 err = mei_cl_read_start(cl); 247 err = mei_cl_read_start(cl, length);
248 if (err && err != -EBUSY) { 248 if (err && err != -EBUSY) {
249 dev_dbg(&dev->pdev->dev, 249 dev_dbg(&dev->pdev->dev,
250 "mei start read failure with status = %d\n", err); 250 "mei start read failure with status = %d\n", err);
@@ -292,9 +292,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
292 } 292 }
293 /* now copy the data to user space */ 293 /* now copy the data to user space */
294copy_buffer: 294copy_buffer:
295 dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n", 295 dev_dbg(&dev->pdev->dev, "buf.size = %d buf.idx= %ld\n",
296 cb->response_buffer.size); 296 cb->response_buffer.size, cb->buf_idx);
297 dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx);
298 if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { 297 if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
299 rets = -EMSGSIZE; 298 rets = -EMSGSIZE;
300 goto free; 299 goto free;