aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2014-03-18 16:52:04 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-03 19:20:24 -0400
commit04bb139a071fef549892718f8965a7c61b1924e0 (patch)
tree3200b716befdaae434220de06efecb59b5db0f60 /drivers/misc
parentcfe5ab85634b5fdab2c90249517910ea3df63f6a (diff)
mei: use runtime pm in write and read flow
Take rpm token on operation start to initiate rpm resume if needed. Mark last busy time, release token and advice rpm framework to try to autosuspend on operation end. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/client.c84
1 files changed, 71 insertions, 13 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 8c078b808cd3..9273e89e6a15 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -18,6 +18,7 @@
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/wait.h> 19#include <linux/wait.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/pm_runtime.h>
21 22
22#include <linux/mei.h> 23#include <linux/mei.h>
23 24
@@ -415,6 +416,10 @@ void mei_host_client_init(struct work_struct *work)
415 dev->reset_count = 0; 416 dev->reset_count = 0;
416 417
417 mutex_unlock(&dev->device_lock); 418 mutex_unlock(&dev->device_lock);
419
420 pm_runtime_mark_last_busy(&dev->pdev->dev);
421 dev_dbg(&dev->pdev->dev, "rpm: autosuspend\n");
422 pm_runtime_autosuspend(&dev->pdev->dev);
418} 423}
419 424
420/** 425/**
@@ -425,6 +430,12 @@ void mei_host_client_init(struct work_struct *work)
425 */ 430 */
426bool mei_hbuf_acquire(struct mei_device *dev) 431bool mei_hbuf_acquire(struct mei_device *dev)
427{ 432{
433 if (mei_pg_state(dev) == MEI_PG_ON ||
434 dev->pg_event == MEI_PG_EVENT_WAIT) {
435 dev_dbg(&dev->pdev->dev, "device is in pg\n");
436 return false;
437 }
438
428 if (!dev->hbuf_is_ready) { 439 if (!dev->hbuf_is_ready) {
429 dev_dbg(&dev->pdev->dev, "hbuf is not ready\n"); 440 dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
430 return false; 441 return false;
@@ -460,9 +471,18 @@ int mei_cl_disconnect(struct mei_cl *cl)
460 if (cl->state != MEI_FILE_DISCONNECTING) 471 if (cl->state != MEI_FILE_DISCONNECTING)
461 return 0; 472 return 0;
462 473
474 rets = pm_runtime_get(&dev->pdev->dev);
475 if (rets < 0 && rets != -EINPROGRESS) {
476 pm_runtime_put_noidle(&dev->pdev->dev);
477 cl_err(dev, cl, "rpm: get failed %d\n", rets);
478 return rets;
479 }
480
463 cb = mei_io_cb_init(cl, NULL); 481 cb = mei_io_cb_init(cl, NULL);
464 if (!cb) 482 if (!cb) {
465 return -ENOMEM; 483 rets = -ENOMEM;
484 goto free;
485 }
466 486
467 cb->fop_type = MEI_FOP_CLOSE; 487 cb->fop_type = MEI_FOP_CLOSE;
468 if (mei_hbuf_acquire(dev)) { 488 if (mei_hbuf_acquire(dev)) {
@@ -494,8 +514,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
494 cl_err(dev, cl, "wrong status client disconnect.\n"); 514 cl_err(dev, cl, "wrong status client disconnect.\n");
495 515
496 if (err) 516 if (err)
497 cl_dbg(dev, cl, "wait failed disconnect err=%08x\n", 517 cl_dbg(dev, cl, "wait failed disconnect err=%d\n", err);
498 err);
499 518
500 cl_err(dev, cl, "failed to disconnect from FW client.\n"); 519 cl_err(dev, cl, "failed to disconnect from FW client.\n");
501 } 520 }
@@ -503,6 +522,10 @@ int mei_cl_disconnect(struct mei_cl *cl)
503 mei_io_list_flush(&dev->ctrl_rd_list, cl); 522 mei_io_list_flush(&dev->ctrl_rd_list, cl);
504 mei_io_list_flush(&dev->ctrl_wr_list, cl); 523 mei_io_list_flush(&dev->ctrl_wr_list, cl);
505free: 524free:
525 cl_dbg(dev, cl, "rpm: autosuspend\n");
526 pm_runtime_mark_last_busy(&dev->pdev->dev);
527 pm_runtime_put_autosuspend(&dev->pdev->dev);
528
506 mei_io_cb_free(cb); 529 mei_io_cb_free(cb);
507 return rets; 530 return rets;
508} 531}
@@ -557,6 +580,13 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
557 580
558 dev = cl->dev; 581 dev = cl->dev;
559 582
583 rets = pm_runtime_get(&dev->pdev->dev);
584 if (rets < 0 && rets != -EINPROGRESS) {
585 pm_runtime_put_noidle(&dev->pdev->dev);
586 cl_err(dev, cl, "rpm: get failed %d\n", rets);
587 return rets;
588 }
589
560 cb = mei_io_cb_init(cl, file); 590 cb = mei_io_cb_init(cl, file);
561 if (!cb) { 591 if (!cb) {
562 rets = -ENOMEM; 592 rets = -ENOMEM;
@@ -596,6 +626,10 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
596 rets = cl->status; 626 rets = cl->status;
597 627
598out: 628out:
629 cl_dbg(dev, cl, "rpm: autosuspend\n");
630 pm_runtime_mark_last_busy(&dev->pdev->dev);
631 pm_runtime_put_autosuspend(&dev->pdev->dev);
632
599 mei_io_cb_free(cb); 633 mei_io_cb_free(cb);
600 return rets; 634 return rets;
601} 635}
@@ -713,23 +747,32 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
713 return -ENOTTY; 747 return -ENOTTY;
714 } 748 }
715 749
750 rets = pm_runtime_get(&dev->pdev->dev);
751 if (rets < 0 && rets != -EINPROGRESS) {
752 pm_runtime_put_noidle(&dev->pdev->dev);
753 cl_err(dev, cl, "rpm: get failed %d\n", rets);
754 return rets;
755 }
756
716 cb = mei_io_cb_init(cl, NULL); 757 cb = mei_io_cb_init(cl, NULL);
717 if (!cb) 758 if (!cb) {
718 return -ENOMEM; 759 rets = -ENOMEM;
760 goto out;
761 }
719 762
720 /* always allocate at least client max message */ 763 /* always allocate at least client max message */
721 length = max_t(size_t, length, dev->me_clients[i].props.max_msg_length); 764 length = max_t(size_t, length, dev->me_clients[i].props.max_msg_length);
722 rets = mei_io_cb_alloc_resp_buf(cb, length); 765 rets = mei_io_cb_alloc_resp_buf(cb, length);
723 if (rets) 766 if (rets)
724 goto err; 767 goto out;
725 768
726 cb->fop_type = MEI_FOP_READ; 769 cb->fop_type = MEI_FOP_READ;
727 if (mei_hbuf_acquire(dev)) { 770 if (mei_hbuf_acquire(dev)) {
728 if (mei_hbm_cl_flow_control_req(dev, cl)) { 771 if (mei_hbm_cl_flow_control_req(dev, cl)) {
729 cl_err(dev, cl, "flow control send failed\n");
730 rets = -ENODEV; 772 rets = -ENODEV;
731 goto err; 773 goto out;
732 } 774 }
775
733 list_add_tail(&cb->list, &dev->read_list.list); 776 list_add_tail(&cb->list, &dev->read_list.list);
734 } else { 777 } else {
735 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 778 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
@@ -737,9 +780,14 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
737 780
738 cl->read_cb = cb; 781 cl->read_cb = cb;
739 782
740 return rets; 783out:
741err: 784 cl_dbg(dev, cl, "rpm: autosuspend\n");
742 mei_io_cb_free(cb); 785 pm_runtime_mark_last_busy(&dev->pdev->dev);
786 pm_runtime_put_autosuspend(&dev->pdev->dev);
787
788 if (rets)
789 mei_io_cb_free(cb);
790
743 return rets; 791 return rets;
744} 792}
745 793
@@ -776,7 +824,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
776 return rets; 824 return rets;
777 825
778 if (rets == 0) { 826 if (rets == 0) {
779 cl_dbg(dev, cl, "No flow control credentials: not sending.\n"); 827 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
780 return 0; 828 return 0;
781 } 829 }
782 830
@@ -856,6 +904,12 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
856 904
857 cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size); 905 cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
858 906
907 rets = pm_runtime_get(&dev->pdev->dev);
908 if (rets < 0 && rets != -EINPROGRESS) {
909 pm_runtime_put_noidle(&dev->pdev->dev);
910 cl_err(dev, cl, "rpm: get failed %d\n", rets);
911 return rets;
912 }
859 913
860 cb->fop_type = MEI_FOP_WRITE; 914 cb->fop_type = MEI_FOP_WRITE;
861 cb->buf_idx = 0; 915 cb->buf_idx = 0;
@@ -926,6 +980,10 @@ out:
926 980
927 rets = buf->size; 981 rets = buf->size;
928err: 982err:
983 cl_dbg(dev, cl, "rpm: autosuspend\n");
984 pm_runtime_mark_last_busy(&dev->pdev->dev);
985 pm_runtime_put_autosuspend(&dev->pdev->dev);
986
929 return rets; 987 return rets;
930} 988}
931 989