diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-04-18 16:03:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-19 13:58:21 -0400 |
commit | 9b0d5efc421ac79d9a6d97c681eff93288093784 (patch) | |
tree | fcde453f66d5eb63dcea84ba9e04f9381ecd1e08 /drivers/misc/mei/hbm.c | |
parent | 3a189b3ba027d4fe79100f728e19e935377f2e60 (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.c | 53 |
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 | ||
126 | int 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 | */ |
131 | void mei_hbm_start_req(struct mei_device *dev) | 152 | int 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; |