aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/hbm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/hbm.c')
-rw-r--r--drivers/misc/mei/hbm.c200
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 */
33static void mei_hbm_me_cl_allocate(struct mei_device *dev) 33static 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 */
157int mei_hbm_start_req(struct mei_device *dev) 157int 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 */
191static void mei_hbm_enum_clients_req(struct mei_device *dev) 193static 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
221static int mei_hbm_prop_req(struct mei_device *dev) 226static 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 */
563void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) 569int 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