diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2014-01-08 13:19:21 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-08 18:25:15 -0500 |
commit | 544f94601409653f07ae6e22d4a39e3a90dceead (patch) | |
tree | 0939fcf8facae8633eebe3fd40b4f4f00788d76e /drivers/misc/mei/hbm.c | |
parent | 634608f27acd098b245ca6fe60e06701185eb170 (diff) |
mei: do not run reset flow from the interrupt thread
This fixes a potential deadlock in case of a firmware
initiated reset
mei_reset has a dialog with the interrupt thread hence
it has to be run from an another work item
Most of the mei_resets were called from mei_hbm_dispatch
which is called in interrupt thread context so this
function underwent major revamp. The error code is
propagated to the interrupt thread and if needed
the reset is scheduled from there.
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/mei/hbm.c')
-rw-r--r-- | drivers/misc/mei/hbm.c | 200 |
1 files changed, 124 insertions, 76 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 9b3a0fb7f265..8109b9a98cc3 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c | |||
@@ -28,9 +28,9 @@ | |||
28 | * | 28 | * |
29 | * @dev: the device structure | 29 | * @dev: the device structure |
30 | * | 30 | * |
31 | * returns none. | 31 | * returns 0 on success -ENOMEM on allocation failure |
32 | */ | 32 | */ |
33 | static void mei_hbm_me_cl_allocate(struct mei_device *dev) | 33 | static int mei_hbm_me_cl_allocate(struct mei_device *dev) |
34 | { | 34 | { |
35 | struct mei_me_client *clients; | 35 | struct mei_me_client *clients; |
36 | int b; | 36 | int b; |
@@ -44,7 +44,7 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev) | |||
44 | dev->me_clients_num++; | 44 | dev->me_clients_num++; |
45 | 45 | ||
46 | if (dev->me_clients_num == 0) | 46 | if (dev->me_clients_num == 0) |
47 | return; | 47 | return 0; |
48 | 48 | ||
49 | kfree(dev->me_clients); | 49 | kfree(dev->me_clients); |
50 | dev->me_clients = NULL; | 50 | dev->me_clients = NULL; |
@@ -56,12 +56,10 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev) | |||
56 | sizeof(struct mei_me_client), GFP_KERNEL); | 56 | sizeof(struct mei_me_client), GFP_KERNEL); |
57 | if (!clients) { | 57 | if (!clients) { |
58 | dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); | 58 | dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); |
59 | dev->dev_state = MEI_DEV_RESETTING; | 59 | return -ENOMEM; |
60 | mei_reset(dev, 1); | ||
61 | return; | ||
62 | } | 60 | } |
63 | dev->me_clients = clients; | 61 | dev->me_clients = clients; |
64 | return; | 62 | return 0; |
65 | } | 63 | } |
66 | 64 | ||
67 | /** | 65 | /** |
@@ -137,7 +135,7 @@ int mei_hbm_start_wait(struct mei_device *dev) | |||
137 | mutex_unlock(&dev->device_lock); | 135 | mutex_unlock(&dev->device_lock); |
138 | ret = wait_event_interruptible_timeout(dev->wait_recvd_msg, | 136 | ret = wait_event_interruptible_timeout(dev->wait_recvd_msg, |
139 | dev->hbm_state == MEI_HBM_IDLE || | 137 | dev->hbm_state == MEI_HBM_IDLE || |
140 | dev->hbm_state > MEI_HBM_START, | 138 | dev->hbm_state >= MEI_HBM_STARTED, |
141 | mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); | 139 | mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); |
142 | mutex_lock(&dev->device_lock); | 140 | mutex_lock(&dev->device_lock); |
143 | 141 | ||
@@ -153,12 +151,15 @@ int mei_hbm_start_wait(struct mei_device *dev) | |||
153 | * mei_hbm_start_req - sends start request message. | 151 | * mei_hbm_start_req - sends start request message. |
154 | * | 152 | * |
155 | * @dev: the device structure | 153 | * @dev: the device structure |
154 | * | ||
155 | * returns 0 on success and < 0 on failure | ||
156 | */ | 156 | */ |
157 | int mei_hbm_start_req(struct mei_device *dev) | 157 | int mei_hbm_start_req(struct mei_device *dev) |
158 | { | 158 | { |
159 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; | 159 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; |
160 | struct hbm_host_version_request *start_req; | 160 | struct hbm_host_version_request *start_req; |
161 | const size_t len = sizeof(struct hbm_host_version_request); | 161 | const size_t len = sizeof(struct hbm_host_version_request); |
162 | int ret; | ||
162 | 163 | ||
163 | mei_hbm_hdr(mei_hdr, len); | 164 | mei_hbm_hdr(mei_hdr, len); |
164 | 165 | ||
@@ -170,12 +171,13 @@ int mei_hbm_start_req(struct mei_device *dev) | |||
170 | start_req->host_version.minor_version = HBM_MINOR_VERSION; | 171 | start_req->host_version.minor_version = HBM_MINOR_VERSION; |
171 | 172 | ||
172 | dev->hbm_state = MEI_HBM_IDLE; | 173 | dev->hbm_state = MEI_HBM_IDLE; |
173 | if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { | 174 | ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data); |
174 | dev_err(&dev->pdev->dev, "version message write failed\n"); | 175 | if (ret) { |
175 | dev->dev_state = MEI_DEV_RESETTING; | 176 | dev_err(&dev->pdev->dev, "version message write failed: ret = %d\n", |
176 | mei_reset(dev, 1); | 177 | ret); |
177 | return -EIO; | 178 | return ret; |
178 | } | 179 | } |
180 | |||
179 | dev->hbm_state = MEI_HBM_START; | 181 | dev->hbm_state = MEI_HBM_START; |
180 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | 182 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
181 | return 0; | 183 | return 0; |
@@ -186,13 +188,15 @@ int mei_hbm_start_req(struct mei_device *dev) | |||
186 | * | 188 | * |
187 | * @dev: the device structure | 189 | * @dev: the device structure |
188 | * | 190 | * |
189 | * returns none. | 191 | * returns 0 on success and < 0 on failure |
190 | */ | 192 | */ |
191 | static void mei_hbm_enum_clients_req(struct mei_device *dev) | 193 | static int mei_hbm_enum_clients_req(struct mei_device *dev) |
192 | { | 194 | { |
193 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; | 195 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; |
194 | struct hbm_host_enum_request *enum_req; | 196 | struct hbm_host_enum_request *enum_req; |
195 | const size_t len = sizeof(struct hbm_host_enum_request); | 197 | const size_t len = sizeof(struct hbm_host_enum_request); |
198 | int ret; | ||
199 | |||
196 | /* enumerate clients */ | 200 | /* enumerate clients */ |
197 | mei_hbm_hdr(mei_hdr, len); | 201 | mei_hbm_hdr(mei_hdr, len); |
198 | 202 | ||
@@ -200,14 +204,15 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev) | |||
200 | memset(enum_req, 0, len); | 204 | memset(enum_req, 0, len); |
201 | enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; | 205 | enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; |
202 | 206 | ||
203 | if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { | 207 | ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data); |
204 | dev->dev_state = MEI_DEV_RESETTING; | 208 | if (ret) { |
205 | dev_err(&dev->pdev->dev, "enumeration request write failed.\n"); | 209 | dev_err(&dev->pdev->dev, "enumeration request write failed: ret = %d.\n", |
206 | mei_reset(dev, 1); | 210 | ret); |
211 | return ret; | ||
207 | } | 212 | } |
208 | dev->hbm_state = MEI_HBM_ENUM_CLIENTS; | 213 | dev->hbm_state = MEI_HBM_ENUM_CLIENTS; |
209 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | 214 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
210 | return; | 215 | return 0; |
211 | } | 216 | } |
212 | 217 | ||
213 | /** | 218 | /** |
@@ -215,7 +220,7 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev) | |||
215 | * | 220 | * |
216 | * @dev: the device structure | 221 | * @dev: the device structure |
217 | * | 222 | * |
218 | * returns none. | 223 | * returns 0 on success and < 0 on failure |
219 | */ | 224 | */ |
220 | 225 | ||
221 | static int mei_hbm_prop_req(struct mei_device *dev) | 226 | static int mei_hbm_prop_req(struct mei_device *dev) |
@@ -226,7 +231,7 @@ static int mei_hbm_prop_req(struct mei_device *dev) | |||
226 | const size_t len = sizeof(struct hbm_props_request); | 231 | const size_t len = sizeof(struct hbm_props_request); |
227 | unsigned long next_client_index; | 232 | unsigned long next_client_index; |
228 | unsigned long client_num; | 233 | unsigned long client_num; |
229 | 234 | int ret; | |
230 | 235 | ||
231 | client_num = dev->me_client_presentation_num; | 236 | client_num = dev->me_client_presentation_num; |
232 | 237 | ||
@@ -253,12 +258,11 @@ static int mei_hbm_prop_req(struct mei_device *dev) | |||
253 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | 258 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; |
254 | prop_req->address = next_client_index; | 259 | prop_req->address = next_client_index; |
255 | 260 | ||
256 | if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { | 261 | ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data); |
257 | dev->dev_state = MEI_DEV_RESETTING; | 262 | if (ret) { |
258 | dev_err(&dev->pdev->dev, "properties request write failed\n"); | 263 | dev_err(&dev->pdev->dev, "properties request write failed: ret = %d\n", |
259 | mei_reset(dev, 1); | 264 | ret); |
260 | 265 | return ret; | |
261 | return -EIO; | ||
262 | } | 266 | } |
263 | 267 | ||
264 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | 268 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
@@ -559,8 +563,10 @@ bool mei_hbm_version_is_supported(struct mei_device *dev) | |||
559 | * | 563 | * |
560 | * @dev: the device structure | 564 | * @dev: the device structure |
561 | * @mei_hdr: header of bus message | 565 | * @mei_hdr: header of bus message |
566 | * | ||
567 | * returns 0 on success and < 0 on failure | ||
562 | */ | 568 | */ |
563 | void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | 569 | int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) |
564 | { | 570 | { |
565 | struct mei_bus_message *mei_msg; | 571 | struct mei_bus_message *mei_msg; |
566 | struct mei_me_client *me_client; | 572 | struct mei_me_client *me_client; |
@@ -579,6 +585,10 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
579 | 585 | ||
580 | switch (mei_msg->hbm_cmd) { | 586 | switch (mei_msg->hbm_cmd) { |
581 | case HOST_START_RES_CMD: | 587 | case HOST_START_RES_CMD: |
588 | dev_dbg(&dev->pdev->dev, "hbm: start: response message received.\n"); | ||
589 | |||
590 | dev->init_clients_timer = 0; | ||
591 | |||
582 | version_res = (struct hbm_host_version_response *)mei_msg; | 592 | version_res = (struct hbm_host_version_response *)mei_msg; |
583 | 593 | ||
584 | dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n", | 594 | dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n", |
@@ -597,73 +607,89 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
597 | } | 607 | } |
598 | 608 | ||
599 | if (!mei_hbm_version_is_supported(dev)) { | 609 | if (!mei_hbm_version_is_supported(dev)) { |
600 | dev_warn(&dev->pdev->dev, "hbm version mismatch: stopping the driver.\n"); | 610 | dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n"); |
601 | 611 | ||
602 | dev->hbm_state = MEI_HBM_STOP; | 612 | dev->hbm_state = MEI_HBM_STOPPED; |
603 | mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, | 613 | mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, |
604 | dev->wr_msg.data); | 614 | dev->wr_msg.data); |
605 | mei_write_message(dev, &dev->wr_msg.hdr, | 615 | if (mei_write_message(dev, &dev->wr_msg.hdr, |
606 | dev->wr_msg.data); | 616 | dev->wr_msg.data)) { |
617 | dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n"); | ||
618 | return -EIO; | ||
619 | } | ||
620 | break; | ||
621 | } | ||
607 | 622 | ||
608 | return; | 623 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || |
624 | dev->hbm_state != MEI_HBM_START) { | ||
625 | dev_err(&dev->pdev->dev, "hbm: start: state mismatch, [%d, %d]\n", | ||
626 | dev->dev_state, dev->hbm_state); | ||
627 | return -EPROTO; | ||
609 | } | 628 | } |
610 | 629 | ||
611 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && | 630 | dev->hbm_state = MEI_HBM_STARTED; |
612 | dev->hbm_state == MEI_HBM_START) { | 631 | |
613 | dev->init_clients_timer = 0; | 632 | if (mei_hbm_enum_clients_req(dev)) { |
614 | mei_hbm_enum_clients_req(dev); | 633 | dev_err(&dev->pdev->dev, "hbm: start: failed to send enumeration request\n"); |
615 | } else { | 634 | return -EIO; |
616 | dev_err(&dev->pdev->dev, "reset: wrong host start response\n"); | ||
617 | mei_reset(dev, 1); | ||
618 | return; | ||
619 | } | 635 | } |
620 | 636 | ||
621 | wake_up_interruptible(&dev->wait_recvd_msg); | 637 | wake_up_interruptible(&dev->wait_recvd_msg); |
622 | dev_dbg(&dev->pdev->dev, "host start response message received.\n"); | ||
623 | break; | 638 | break; |
624 | 639 | ||
625 | case CLIENT_CONNECT_RES_CMD: | 640 | case CLIENT_CONNECT_RES_CMD: |
641 | dev_dbg(&dev->pdev->dev, "hbm: client connect response: message received.\n"); | ||
642 | |||
626 | connect_res = (struct hbm_client_connect_response *) mei_msg; | 643 | connect_res = (struct hbm_client_connect_response *) mei_msg; |
627 | mei_hbm_cl_connect_res(dev, connect_res); | 644 | mei_hbm_cl_connect_res(dev, connect_res); |
628 | dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); | ||
629 | wake_up(&dev->wait_recvd_msg); | 645 | wake_up(&dev->wait_recvd_msg); |
630 | break; | 646 | break; |
631 | 647 | ||
632 | case CLIENT_DISCONNECT_RES_CMD: | 648 | case CLIENT_DISCONNECT_RES_CMD: |
649 | dev_dbg(&dev->pdev->dev, "hbm: client disconnect response: message received.\n"); | ||
650 | |||
633 | disconnect_res = (struct hbm_client_connect_response *) mei_msg; | 651 | disconnect_res = (struct hbm_client_connect_response *) mei_msg; |
634 | mei_hbm_cl_disconnect_res(dev, disconnect_res); | 652 | mei_hbm_cl_disconnect_res(dev, disconnect_res); |
635 | dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); | ||
636 | wake_up(&dev->wait_recvd_msg); | 653 | wake_up(&dev->wait_recvd_msg); |
637 | break; | 654 | break; |
638 | 655 | ||
639 | case MEI_FLOW_CONTROL_CMD: | 656 | case MEI_FLOW_CONTROL_CMD: |
657 | dev_dbg(&dev->pdev->dev, "hbm: client flow control response: message received.\n"); | ||
658 | |||
640 | flow_control = (struct hbm_flow_control *) mei_msg; | 659 | flow_control = (struct hbm_flow_control *) mei_msg; |
641 | mei_hbm_cl_flow_control_res(dev, flow_control); | 660 | mei_hbm_cl_flow_control_res(dev, flow_control); |
642 | dev_dbg(&dev->pdev->dev, "client flow control response message received.\n"); | ||
643 | break; | 661 | break; |
644 | 662 | ||
645 | case HOST_CLIENT_PROPERTIES_RES_CMD: | 663 | case HOST_CLIENT_PROPERTIES_RES_CMD: |
664 | dev_dbg(&dev->pdev->dev, "hbm: properties response: message received.\n"); | ||
665 | |||
666 | dev->init_clients_timer = 0; | ||
667 | |||
668 | if (dev->me_clients == NULL) { | ||
669 | dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n"); | ||
670 | return -EPROTO; | ||
671 | } | ||
672 | |||
646 | props_res = (struct hbm_props_response *)mei_msg; | 673 | props_res = (struct hbm_props_response *)mei_msg; |
647 | me_client = &dev->me_clients[dev->me_client_presentation_num]; | 674 | me_client = &dev->me_clients[dev->me_client_presentation_num]; |
648 | 675 | ||
649 | if (props_res->status || !dev->me_clients) { | 676 | if (props_res->status) { |
650 | dev_err(&dev->pdev->dev, "reset: properties response hbm wrong status.\n"); | 677 | dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n", |
651 | mei_reset(dev, 1); | 678 | props_res->status); |
652 | return; | 679 | return -EPROTO; |
653 | } | 680 | } |
654 | 681 | ||
655 | if (me_client->client_id != props_res->address) { | 682 | if (me_client->client_id != props_res->address) { |
656 | dev_err(&dev->pdev->dev, "reset: host properties response address mismatch\n"); | 683 | dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n", |
657 | mei_reset(dev, 1); | 684 | me_client->client_id, props_res->address); |
658 | return; | 685 | return -EPROTO; |
659 | } | 686 | } |
660 | 687 | ||
661 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || | 688 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || |
662 | dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) { | 689 | dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) { |
663 | dev_err(&dev->pdev->dev, "reset: unexpected properties response\n"); | 690 | dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n", |
664 | mei_reset(dev, 1); | 691 | dev->dev_state, dev->hbm_state); |
665 | 692 | return -EPROTO; | |
666 | return; | ||
667 | } | 693 | } |
668 | 694 | ||
669 | me_client->props = props_res->client_properties; | 695 | me_client->props = props_res->client_properties; |
@@ -671,49 +697,70 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
671 | dev->me_client_presentation_num++; | 697 | dev->me_client_presentation_num++; |
672 | 698 | ||
673 | /* request property for the next client */ | 699 | /* request property for the next client */ |
674 | mei_hbm_prop_req(dev); | 700 | if (mei_hbm_prop_req(dev)) |
701 | return -EIO; | ||
675 | 702 | ||
676 | break; | 703 | break; |
677 | 704 | ||
678 | case HOST_ENUM_RES_CMD: | 705 | case HOST_ENUM_RES_CMD: |
706 | dev_dbg(&dev->pdev->dev, "hbm: enumeration response: message received\n"); | ||
707 | |||
708 | dev->init_clients_timer = 0; | ||
709 | |||
679 | enum_res = (struct hbm_host_enum_response *) mei_msg; | 710 | enum_res = (struct hbm_host_enum_response *) mei_msg; |
680 | BUILD_BUG_ON(sizeof(dev->me_clients_map) | 711 | BUILD_BUG_ON(sizeof(dev->me_clients_map) |
681 | < sizeof(enum_res->valid_addresses)); | 712 | < sizeof(enum_res->valid_addresses)); |
682 | memcpy(dev->me_clients_map, enum_res->valid_addresses, | 713 | memcpy(dev->me_clients_map, enum_res->valid_addresses, |
683 | sizeof(enum_res->valid_addresses)); | 714 | sizeof(enum_res->valid_addresses)); |
684 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && | 715 | |
685 | dev->hbm_state == MEI_HBM_ENUM_CLIENTS) { | 716 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || |
686 | dev->init_clients_timer = 0; | 717 | dev->hbm_state != MEI_HBM_ENUM_CLIENTS) { |
687 | mei_hbm_me_cl_allocate(dev); | 718 | dev_err(&dev->pdev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n", |
688 | dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES; | 719 | dev->dev_state, dev->hbm_state); |
689 | 720 | return -EPROTO; | |
690 | /* first property reqeust */ | ||
691 | mei_hbm_prop_req(dev); | ||
692 | } else { | ||
693 | dev_err(&dev->pdev->dev, "reset: unexpected enumeration response hbm.\n"); | ||
694 | mei_reset(dev, 1); | ||
695 | return; | ||
696 | } | 721 | } |
722 | |||
723 | if (mei_hbm_me_cl_allocate(dev)) { | ||
724 | dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n"); | ||
725 | return -ENOMEM; | ||
726 | } | ||
727 | |||
728 | dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES; | ||
729 | |||
730 | /* first property request */ | ||
731 | if (mei_hbm_prop_req(dev)) | ||
732 | return -EIO; | ||
733 | |||
697 | break; | 734 | break; |
698 | 735 | ||
699 | case HOST_STOP_RES_CMD: | 736 | case HOST_STOP_RES_CMD: |
737 | dev_dbg(&dev->pdev->dev, "hbm: stop response: message received\n"); | ||
738 | |||
739 | dev->init_clients_timer = 0; | ||
740 | |||
741 | if (dev->hbm_state != MEI_HBM_STOPPED) { | ||
742 | dev_err(&dev->pdev->dev, "hbm: stop response: state mismatch, [%d, %d]\n", | ||
743 | dev->dev_state, dev->hbm_state); | ||
744 | return -EPROTO; | ||
745 | } | ||
700 | 746 | ||
701 | if (dev->hbm_state != MEI_HBM_STOP) | ||
702 | dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n"); | ||
703 | dev->dev_state = MEI_DEV_DISABLED; | 747 | dev->dev_state = MEI_DEV_DISABLED; |
704 | dev_info(&dev->pdev->dev, "reset: FW stop response.\n"); | 748 | dev_info(&dev->pdev->dev, "hbm: stop response: resetting.\n"); |
705 | mei_reset(dev, 1); | 749 | /* force the reset */ |
750 | return -EPROTO; | ||
706 | break; | 751 | break; |
707 | 752 | ||
708 | case CLIENT_DISCONNECT_REQ_CMD: | 753 | case CLIENT_DISCONNECT_REQ_CMD: |
709 | /* search for client */ | 754 | dev_dbg(&dev->pdev->dev, "hbm: disconnect request: message received\n"); |
755 | |||
710 | disconnect_req = (struct hbm_client_connect_request *)mei_msg; | 756 | disconnect_req = (struct hbm_client_connect_request *)mei_msg; |
711 | mei_hbm_fw_disconnect_req(dev, disconnect_req); | 757 | mei_hbm_fw_disconnect_req(dev, disconnect_req); |
712 | break; | 758 | break; |
713 | 759 | ||
714 | case ME_STOP_REQ_CMD: | 760 | case ME_STOP_REQ_CMD: |
761 | dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n"); | ||
715 | 762 | ||
716 | dev->hbm_state = MEI_HBM_STOP; | 763 | dev->hbm_state = MEI_HBM_STOPPED; |
717 | mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, | 764 | mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, |
718 | dev->wr_ext_msg.data); | 765 | dev->wr_ext_msg.data); |
719 | break; | 766 | break; |
@@ -722,5 +769,6 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
722 | break; | 769 | break; |
723 | 770 | ||
724 | } | 771 | } |
772 | return 0; | ||
725 | } | 773 | } |
726 | 774 | ||