aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/hbm.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-04-18 16:03:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-19 13:58:21 -0400
commit9b0d5efc421ac79d9a6d97c681eff93288093784 (patch)
treefcde453f66d5eb63dcea84ba9e04f9381ecd1e08 /drivers/misc/mei/hbm.c
parent3a189b3ba027d4fe79100f728e19e935377f2e60 (diff)
mei: revamp hbm state machine
1. Rename init_clients_state to hbm_state and use MEI_HBM_ prefix for HBM states 2. Remove recvd_msg and use hbm state for synchronizing hbm protocol has successful start. We can wake up the hbm event from start response handler and remove the hack from the interrupt thread 3. mei_hbm_start_wait function encapsulate start completion waiting Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/hbm.c')
-rw-r--r--drivers/misc/mei/hbm.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index de7f5ba3194f..4de80d9b7c45 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -123,12 +123,33 @@ static bool is_treat_specially_client(struct mei_cl *cl,
123 return false; 123 return false;
124} 124}
125 125
126int mei_hbm_start_wait(struct mei_device *dev)
127{
128 int ret;
129 if (dev->hbm_state > MEI_HBM_START)
130 return 0;
131
132 mutex_unlock(&dev->device_lock);
133 ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
134 dev->hbm_state == MEI_HBM_IDLE ||
135 dev->hbm_state > MEI_HBM_START,
136 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
137 mutex_lock(&dev->device_lock);
138
139 if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
140 dev->hbm_state = MEI_HBM_IDLE;
141 dev_err(&dev->pdev->dev, "wating for mei start failed\n");
142 return -ETIMEDOUT;
143 }
144 return 0;
145}
146
126/** 147/**
127 * mei_hbm_start_req - sends start request message. 148 * mei_hbm_start_req - sends start request message.
128 * 149 *
129 * @dev: the device structure 150 * @dev: the device structure
130 */ 151 */
131void mei_hbm_start_req(struct mei_device *dev) 152int mei_hbm_start_req(struct mei_device *dev)
132{ 153{
133 struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; 154 struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
134 struct hbm_host_version_request *start_req; 155 struct hbm_host_version_request *start_req;
@@ -143,18 +164,19 @@ void mei_hbm_start_req(struct mei_device *dev)
143 start_req->host_version.major_version = HBM_MAJOR_VERSION; 164 start_req->host_version.major_version = HBM_MAJOR_VERSION;
144 start_req->host_version.minor_version = HBM_MINOR_VERSION; 165 start_req->host_version.minor_version = HBM_MINOR_VERSION;
145 166
146 dev->recvd_msg = false; 167 dev->hbm_state = MEI_HBM_IDLE;
147 if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { 168 if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
148 dev_err(&dev->pdev->dev, "version message writet failed\n"); 169 dev_err(&dev->pdev->dev, "version message writet failed\n");
149 dev->dev_state = MEI_DEV_RESETING; 170 dev->dev_state = MEI_DEV_RESETING;
150 mei_reset(dev, 1); 171 mei_reset(dev, 1);
172 return -ENODEV;
151 } 173 }
152 dev->init_clients_state = MEI_START_MESSAGE; 174 dev->hbm_state = MEI_HBM_START;
153 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 175 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
154 return ; 176 return 0;
155} 177}
156 178
157/** 179/*
158 * mei_hbm_enum_clients_req - sends enumeration client request message. 180 * mei_hbm_enum_clients_req - sends enumeration client request message.
159 * 181 *
160 * @dev: the device structure 182 * @dev: the device structure
@@ -178,7 +200,7 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev)
178 dev_err(&dev->pdev->dev, "enumeration request write failed.\n"); 200 dev_err(&dev->pdev->dev, "enumeration request write failed.\n");
179 mei_reset(dev, 1); 201 mei_reset(dev, 1);
180 } 202 }
181 dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; 203 dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
182 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 204 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
183 return; 205 return;
184} 206}
@@ -208,6 +230,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
208 230
209 /* We got all client properties */ 231 /* We got all client properties */
210 if (next_client_index == MEI_CLIENTS_MAX) { 232 if (next_client_index == MEI_CLIENTS_MAX) {
233 dev->hbm_state = MEI_HBM_STARTED;
211 schedule_work(&dev->init_work); 234 schedule_work(&dev->init_work);
212 235
213 return 0; 236 return 0;
@@ -542,27 +565,28 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
542 dev->version = version_res->me_max_version; 565 dev->version = version_res->me_max_version;
543 dev_dbg(&dev->pdev->dev, "version mismatch.\n"); 566 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
544 567
568 dev->hbm_state = MEI_HBM_STOP;
545 mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, 569 mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
546 dev->wr_msg.data); 570 dev->wr_msg.data);
547 mei_write_message(dev, &dev->wr_msg.hdr, 571 mei_write_message(dev, &dev->wr_msg.hdr,
548 dev->wr_msg.data); 572 dev->wr_msg.data);
573
549 return; 574 return;
550 } 575 }
551 576
552 dev->version.major_version = HBM_MAJOR_VERSION; 577 dev->version.major_version = HBM_MAJOR_VERSION;
553 dev->version.minor_version = HBM_MINOR_VERSION; 578 dev->version.minor_version = HBM_MINOR_VERSION;
554 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 579 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
555 dev->init_clients_state == MEI_START_MESSAGE) { 580 dev->hbm_state == MEI_HBM_START) {
556 dev->init_clients_timer = 0; 581 dev->init_clients_timer = 0;
557 mei_hbm_enum_clients_req(dev); 582 mei_hbm_enum_clients_req(dev);
558 } else { 583 } else {
559 dev->recvd_msg = false;
560 dev_err(&dev->pdev->dev, "reset: wrong host start response\n"); 584 dev_err(&dev->pdev->dev, "reset: wrong host start response\n");
561 mei_reset(dev, 1); 585 mei_reset(dev, 1);
562 return; 586 return;
563 } 587 }
564 588
565 dev->recvd_msg = true; 589 wake_up_interruptible(&dev->wait_recvd_msg);
566 dev_dbg(&dev->pdev->dev, "host start response message received.\n"); 590 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
567 break; 591 break;
568 592
@@ -603,7 +627,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
603 } 627 }
604 628
605 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 629 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
606 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { 630 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
607 dev_err(&dev->pdev->dev, "reset: unexpected properties response\n"); 631 dev_err(&dev->pdev->dev, "reset: unexpected properties response\n");
608 mei_reset(dev, 1); 632 mei_reset(dev, 1);
609 633
@@ -623,13 +647,12 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
623 enum_res = (struct hbm_host_enum_response *) mei_msg; 647 enum_res = (struct hbm_host_enum_response *) mei_msg;
624 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 648 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
625 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 649 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
626 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { 650 dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
627 dev->init_clients_timer = 0; 651 dev->init_clients_timer = 0;
628 dev->me_client_presentation_num = 0; 652 dev->me_client_presentation_num = 0;
629 dev->me_client_index = 0; 653 dev->me_client_index = 0;
630 mei_hbm_me_cl_allocate(dev); 654 mei_hbm_me_cl_allocate(dev);
631 dev->init_clients_state = 655 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
632 MEI_CLIENT_PROPERTIES_MESSAGE;
633 656
634 /* first property reqeust */ 657 /* first property reqeust */
635 mei_hbm_prop_req(dev); 658 mei_hbm_prop_req(dev);
@@ -641,6 +664,9 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
641 break; 664 break;
642 665
643 case HOST_STOP_RES_CMD: 666 case HOST_STOP_RES_CMD:
667
668 if (dev->hbm_state != MEI_HBM_STOP)
669 dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n");
644 dev->dev_state = MEI_DEV_DISABLED; 670 dev->dev_state = MEI_DEV_DISABLED;
645 dev_info(&dev->pdev->dev, "reset: FW stop response.\n"); 671 dev_info(&dev->pdev->dev, "reset: FW stop response.\n");
646 mei_reset(dev, 1); 672 mei_reset(dev, 1);
@@ -654,6 +680,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
654 680
655 case ME_STOP_REQ_CMD: 681 case ME_STOP_REQ_CMD:
656 682
683 dev->hbm_state = MEI_HBM_STOP;
657 mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, 684 mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
658 dev->wr_ext_msg.data); 685 dev->wr_ext_msg.data);
659 break; 686 break;