diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2015-02-10 03:39:37 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-01 22:37:00 -0500 |
commit | db4756fd2f16efae8469dd1e37710919a0af9370 (patch) | |
tree | a7c6c91ac6a2345e397f2e23d3513b3d5e10ebf1 | |
parent | 3d33ff2457355a9dd3c3178b04ab6669882b306c (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.c | 76 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 7 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 2 |
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 | */ |
510 | int mei_amthif_irq_read_msg(struct mei_device *dev, | 513 | int 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 | |||
565 | err: | ||
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 | ||
687 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); | 687 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); |
688 | int mei_amthif_irq_read_msg(struct mei_device *dev, | 688 | int 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); |
691 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | 691 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); |