aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-02-10 03:39:37 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-01 22:37:00 -0500
commitdb4756fd2f16efae8469dd1e37710919a0af9370 (patch)
treea7c6c91ac6a2345e397f2e23d3513b3d5e10ebf1
parent3d33ff2457355a9dd3c3178b04ab6669882b306c (diff)
mei: iamthif: fix device reset on mei_amthif_irq_read_msg
On failure mei_amthif_irq_read_msg returns an error that will cause device reset but the issue is software one so instead we should propagate error to caller and just clean the read queues. As a side effect also removes useless BUG_ONs Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mei/amthif.c76
-rw-r--r--drivers/misc/mei/interrupt.c7
-rw-r--r--drivers/misc/mei/mei_dev.h2
3 files changed, 51 insertions, 34 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index c4cb9a984a5f..2ad2f94678c8 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -195,23 +195,26 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
195 dev_dbg(dev->dev, "woke up from sleep\n"); 195 dev_dbg(dev->dev, "woke up from sleep\n");
196 } 196 }
197 197
198 if (cb->status) {
199 rets = cb->status;
200 dev_dbg(dev->dev, "read operation failed %d\n", rets);
201 goto free;
202 }
198 203
199 dev_dbg(dev->dev, "Got amthif data\n"); 204 dev_dbg(dev->dev, "Got amthif data\n");
200 dev->iamthif_timer = 0; 205 dev->iamthif_timer = 0;
201 206
202 if (cb) { 207 timeout = cb->read_time +
203 timeout = cb->read_time + 208 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
204 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); 209 dev_dbg(dev->dev, "amthif timeout = %lud\n",
205 dev_dbg(dev->dev, "amthif timeout = %lud\n", 210 timeout);
206 timeout); 211
207 212 if (time_after(jiffies, timeout)) {
208 if (time_after(jiffies, timeout)) { 213 dev_dbg(dev->dev, "amthif Time out\n");
209 dev_dbg(dev->dev, "amthif Time out\n"); 214 /* 15 sec for the message has expired */
210 /* 15 sec for the message has expired */ 215 list_del(&cb->list);
211 list_del(&cb->list); 216 rets = -ETIME;
212 rets = -ETIME; 217 goto free;
213 goto free;
214 }
215 } 218 }
216 /* if the whole message will fit remove it from the list */ 219 /* if the whole message will fit remove it from the list */
217 if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) 220 if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
@@ -501,25 +504,42 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
501 * mei_amthif_irq_read_msg - read routine after ISR to 504 * mei_amthif_irq_read_msg - read routine after ISR to
502 * handle the read amthif message 505 * handle the read amthif message
503 * 506 *
504 * @dev: the device structure 507 * @cl: mei client
505 * @mei_hdr: header of amthif message 508 * @mei_hdr: header of amthif message
506 * @complete_list: An instance of our list structure 509 * @complete_list: completed callbacks list
507 * 510 *
508 * Return: 0 on success, <0 on failure. 511 * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
509 */ 512 */
510int mei_amthif_irq_read_msg(struct mei_device *dev, 513int mei_amthif_irq_read_msg(struct mei_cl *cl,
511 struct mei_msg_hdr *mei_hdr, 514 struct mei_msg_hdr *mei_hdr,
512 struct mei_cl_cb *complete_list) 515 struct mei_cl_cb *complete_list)
513{ 516{
517 struct mei_device *dev;
514 struct mei_cl_cb *cb; 518 struct mei_cl_cb *cb;
515 unsigned char *buffer; 519 unsigned char *buffer;
520 int ret = 0;
516 521
517 BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); 522 dev = cl->dev;
518 BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
519 523
520 buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; 524 if (cl->state != MEI_FILE_CONNECTED)
521 BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); 525 goto err;
526
527 if (dev->iamthif_state != MEI_IAMTHIF_READING)
528 goto err;
529
530 cb = dev->iamthif_current_cb;
522 531
532 if (!cb) {
533 ret = -ENODEV;
534 goto err;
535 }
536
537 if (dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length) {
538 cb->status = -ERANGE;
539 goto err;
540 }
541
542 buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
523 mei_read_slots(dev, buffer, mei_hdr->length); 543 mei_read_slots(dev, buffer, mei_hdr->length);
524 544
525 dev->iamthif_msg_buf_index += mei_hdr->length; 545 dev->iamthif_msg_buf_index += mei_hdr->length;
@@ -527,14 +547,8 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
527 if (!mei_hdr->msg_complete) 547 if (!mei_hdr->msg_complete)
528 return 0; 548 return 0;
529 549
530 dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
531 mei_hdr->length);
532
533 dev_dbg(dev->dev, "completed amthif read.\n "); 550 dev_dbg(dev->dev, "completed amthif read.\n ");
534 if (!dev->iamthif_current_cb)
535 return -ENODEV;
536 551
537 cb = dev->iamthif_current_cb;
538 dev->iamthif_current_cb = NULL; 552 dev->iamthif_current_cb = NULL;
539 553
540 dev->iamthif_stall_timer = 0; 554 dev->iamthif_stall_timer = 0;
@@ -543,10 +557,16 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
543 if (dev->iamthif_ioctl) { 557 if (dev->iamthif_ioctl) {
544 /* found the iamthif cb */ 558 /* found the iamthif cb */
545 dev_dbg(dev->dev, "complete the amthif read cb.\n "); 559 dev_dbg(dev->dev, "complete the amthif read cb.\n ");
546 dev_dbg(dev->dev, "add the amthif read cb to complete.\n ");
547 list_add_tail(&cb->list, &complete_list->list); 560 list_add_tail(&cb->list, &complete_list->list);
548 } 561 }
562
549 return 0; 563 return 0;
564
565err:
566 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
567 dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
568 MEI_HDR_PRM(mei_hdr));
569 return ret;
550} 570}
551 571
552/** 572/**
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 587cb04a3cf5..151f0c84a65e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -384,11 +384,8 @@ int mei_irq_read_handler(struct mei_device *dev,
384 goto end; 384 goto end;
385 } 385 }
386 386
387 if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 387 if (cl == &dev->iamthif_cl) {
388 MEI_FILE_CONNECTED == dev->iamthif_cl.state && 388 ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
389 dev->iamthif_state == MEI_IAMTHIF_READING) {
390
391 ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
392 if (ret) { 389 if (ret) {
393 dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n", 390 dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
394 ret); 391 ret);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 195e426b08f0..b74d156ed600 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -685,7 +685,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
685 struct mei_cl_cb *cmpl_list); 685 struct mei_cl_cb *cmpl_list);
686 686
687void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); 687void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
688int mei_amthif_irq_read_msg(struct mei_device *dev, 688int mei_amthif_irq_read_msg(struct mei_cl *cl,
689 struct mei_msg_hdr *mei_hdr, 689 struct mei_msg_hdr *mei_hdr,
690 struct mei_cl_cb *complete_list); 690 struct mei_cl_cb *complete_list);
691int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); 691int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);