Merge remote-tracking branch 'lsk/v3.10/topic/arm64-ptrace' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mei / hbm.c
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2012, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #include <linux/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/mei.h>
21
22 #include "mei_dev.h"
23 #include "hbm.h"
24 #include "hw-me.h"
25
26 /**
27  * mei_hbm_me_cl_allocate - allocates storage for me clients
28  *
29  * @dev: the device structure
30  *
31  * returns none.
32  */
33 static void mei_hbm_me_cl_allocate(struct mei_device *dev)
34 {
35         struct mei_me_client *clients;
36         int b;
37
38         dev->me_clients_num = 0;
39         dev->me_client_presentation_num = 0;
40         dev->me_client_index = 0;
41
42         /* count how many ME clients we have */
43         for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
44                 dev->me_clients_num++;
45
46         if (dev->me_clients_num == 0)
47                 return;
48
49         kfree(dev->me_clients);
50         dev->me_clients = NULL;
51
52         dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
53                 dev->me_clients_num * sizeof(struct mei_me_client));
54         /* allocate storage for ME clients representation */
55         clients = kcalloc(dev->me_clients_num,
56                         sizeof(struct mei_me_client), GFP_KERNEL);
57         if (!clients) {
58                 dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
59                 dev->dev_state = MEI_DEV_RESETTING;
60                 mei_reset(dev, 1);
61                 return;
62         }
63         dev->me_clients = clients;
64         return;
65 }
66
67 /**
68  * mei_hbm_cl_hdr - construct client hbm header
69  *
70  * @cl: - client
71  * @hbm_cmd: host bus message command
72  * @buf: buffer for cl header
73  * @len: buffer length
74  */
75 static inline
76 void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
77 {
78         struct mei_hbm_cl_cmd *cmd = buf;
79
80         memset(cmd, 0, len);
81
82         cmd->hbm_cmd = hbm_cmd;
83         cmd->host_addr = cl->host_client_id;
84         cmd->me_addr = cl->me_client_id;
85 }
86
87 /**
88  * same_disconn_addr - tells if they have the same address
89  *
90  * @file: private data of the file object.
91  * @disconn: disconnection request.
92  *
93  * returns true if addres are same
94  */
95 static inline
96 bool mei_hbm_cl_addr_equal(struct mei_cl *cl, void *buf)
97 {
98         struct mei_hbm_cl_cmd *cmd = buf;
99         return cl->host_client_id == cmd->host_addr &&
100                 cl->me_client_id == cmd->me_addr;
101 }
102
103
104 /**
105  * is_treat_specially_client - checks if the message belongs
106  * to the file private data.
107  *
108  * @cl: private data of the file object
109  * @rs: connect response bus message
110  *
111  */
112 static bool is_treat_specially_client(struct mei_cl *cl,
113                 struct hbm_client_connect_response *rs)
114 {
115         if (mei_hbm_cl_addr_equal(cl, rs)) {
116                 if (!rs->status) {
117                         cl->state = MEI_FILE_CONNECTED;
118                         cl->status = 0;
119
120                 } else {
121                         cl->state = MEI_FILE_DISCONNECTED;
122                         cl->status = -ENODEV;
123                 }
124                 cl->timer_count = 0;
125
126                 return true;
127         }
128         return false;
129 }
130
131 int mei_hbm_start_wait(struct mei_device *dev)
132 {
133         int ret;
134         if (dev->hbm_state > MEI_HBM_START)
135                 return 0;
136
137         mutex_unlock(&dev->device_lock);
138         ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
139                         dev->hbm_state == MEI_HBM_IDLE ||
140                         dev->hbm_state > MEI_HBM_START,
141                         mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
142         mutex_lock(&dev->device_lock);
143
144         if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
145                 dev->hbm_state = MEI_HBM_IDLE;
146                 dev_err(&dev->pdev->dev, "wating for mei start failed\n");
147                 return -ETIMEDOUT;
148         }
149         return 0;
150 }
151
152 /**
153  * mei_hbm_start_req - sends start request message.
154  *
155  * @dev: the device structure
156  */
157 int mei_hbm_start_req(struct mei_device *dev)
158 {
159         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
160         struct hbm_host_version_request *start_req;
161         const size_t len = sizeof(struct hbm_host_version_request);
162
163         mei_hbm_hdr(mei_hdr, len);
164
165         /* host start message */
166         start_req = (struct hbm_host_version_request *)dev->wr_msg.data;
167         memset(start_req, 0, len);
168         start_req->hbm_cmd = HOST_START_REQ_CMD;
169         start_req->host_version.major_version = HBM_MAJOR_VERSION;
170         start_req->host_version.minor_version = HBM_MINOR_VERSION;
171
172         dev->hbm_state = MEI_HBM_IDLE;
173         if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
174                 dev_err(&dev->pdev->dev, "version message writet failed\n");
175                 dev->dev_state = MEI_DEV_RESETTING;
176                 mei_reset(dev, 1);
177                 return -ENODEV;
178         }
179         dev->hbm_state = MEI_HBM_START;
180         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
181         return 0;
182 }
183
184 /*
185  * mei_hbm_enum_clients_req - sends enumeration client request message.
186  *
187  * @dev: the device structure
188  *
189  * returns none.
190  */
191 static void mei_hbm_enum_clients_req(struct mei_device *dev)
192 {
193         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
194         struct hbm_host_enum_request *enum_req;
195         const size_t len = sizeof(struct hbm_host_enum_request);
196         /* enumerate clients */
197         mei_hbm_hdr(mei_hdr, len);
198
199         enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data;
200         memset(enum_req, 0, len);
201         enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
202
203         if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
204                 dev->dev_state = MEI_DEV_RESETTING;
205                 dev_err(&dev->pdev->dev, "enumeration request write failed.\n");
206                 mei_reset(dev, 1);
207         }
208         dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
209         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
210         return;
211 }
212
213 /**
214  * mei_hbm_prop_req - request property for a single client
215  *
216  * @dev: the device structure
217  *
218  * returns none.
219  */
220
221 static int mei_hbm_prop_req(struct mei_device *dev)
222 {
223
224         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
225         struct hbm_props_request *prop_req;
226         const size_t len = sizeof(struct hbm_props_request);
227         unsigned long next_client_index;
228         unsigned long client_num;
229
230
231         client_num = dev->me_client_presentation_num;
232
233         next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
234                                           dev->me_client_index);
235
236         /* We got all client properties */
237         if (next_client_index == MEI_CLIENTS_MAX) {
238                 dev->hbm_state = MEI_HBM_STARTED;
239                 schedule_work(&dev->init_work);
240
241                 return 0;
242         }
243
244         dev->me_clients[client_num].client_id = next_client_index;
245         dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
246
247         mei_hbm_hdr(mei_hdr, len);
248         prop_req = (struct hbm_props_request *)dev->wr_msg.data;
249
250         memset(prop_req, 0, sizeof(struct hbm_props_request));
251
252
253         prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
254         prop_req->address = next_client_index;
255
256         if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
257                 dev->dev_state = MEI_DEV_RESETTING;
258                 dev_err(&dev->pdev->dev, "properties request write failed\n");
259                 mei_reset(dev, 1);
260
261                 return -EIO;
262         }
263
264         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
265         dev->me_client_index = next_client_index;
266
267         return 0;
268 }
269
270 /**
271  * mei_hbm_stop_req_prepare - perpare stop request message
272  *
273  * @dev - mei device
274  * @mei_hdr - mei message header
275  * @data - hbm message body buffer
276  */
277 static void mei_hbm_stop_req_prepare(struct mei_device *dev,
278                 struct mei_msg_hdr *mei_hdr, unsigned char *data)
279 {
280         struct hbm_host_stop_request *req =
281                         (struct hbm_host_stop_request *)data;
282         const size_t len = sizeof(struct hbm_host_stop_request);
283
284         mei_hbm_hdr(mei_hdr, len);
285
286         memset(req, 0, len);
287         req->hbm_cmd = HOST_STOP_REQ_CMD;
288         req->reason = DRIVER_STOP_REQUEST;
289 }
290
291 /**
292  * mei_hbm_cl_flow_control_req - sends flow control requst.
293  *
294  * @dev: the device structure
295  * @cl: client info
296  *
297  * This function returns -EIO on write failure
298  */
299 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
300 {
301         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
302         const size_t len = sizeof(struct hbm_flow_control);
303
304         mei_hbm_hdr(mei_hdr, len);
305         mei_hbm_cl_hdr(cl, MEI_FLOW_CONTROL_CMD, dev->wr_msg.data, len);
306
307         dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
308                 cl->host_client_id, cl->me_client_id);
309
310         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
311 }
312
313 /**
314  * mei_hbm_add_single_flow_creds - adds single buffer credentials.
315  *
316  * @dev: the device structure
317  * @flow: flow control.
318  */
319 static void mei_hbm_add_single_flow_creds(struct mei_device *dev,
320                                   struct hbm_flow_control *flow)
321 {
322         struct mei_me_client *client;
323         int i;
324
325         for (i = 0; i < dev->me_clients_num; i++) {
326                 client = &dev->me_clients[i];
327                 if (client && flow->me_addr == client->client_id) {
328                         if (client->props.single_recv_buf) {
329                                 client->mei_flow_ctrl_creds++;
330                                 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
331                                     flow->me_addr);
332                                 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
333                                     client->mei_flow_ctrl_creds);
334                         } else {
335                                 BUG();  /* error in flow control */
336                         }
337                 }
338         }
339 }
340
341 /**
342  * mei_hbm_cl_flow_control_res - flow control response from me
343  *
344  * @dev: the device structure
345  * @flow_control: flow control response bus message
346  */
347 static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
348                 struct hbm_flow_control *flow_control)
349 {
350         struct mei_cl *cl = NULL;
351         struct mei_cl *next = NULL;
352
353         if (!flow_control->host_addr) {
354                 /* single receive buffer */
355                 mei_hbm_add_single_flow_creds(dev, flow_control);
356                 return;
357         }
358
359         /* normal connection */
360         list_for_each_entry_safe(cl, next, &dev->file_list, link) {
361                 if (mei_hbm_cl_addr_equal(cl, flow_control)) {
362                         cl->mei_flow_ctrl_creds++;
363                         dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
364                                 flow_control->host_addr, flow_control->me_addr);
365                         dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
366                                     cl->mei_flow_ctrl_creds);
367                                 break;
368                 }
369         }
370 }
371
372
373 /**
374  * mei_hbm_cl_disconnect_req - sends disconnect message to fw.
375  *
376  * @dev: the device structure
377  * @cl: a client to disconnect from
378  *
379  * This function returns -EIO on write failure
380  */
381 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
382 {
383         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
384         const size_t len = sizeof(struct hbm_client_connect_request);
385
386         mei_hbm_hdr(mei_hdr, len);
387         mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, dev->wr_msg.data, len);
388
389         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
390 }
391
392 /**
393  * mei_hbm_cl_disconnect_res - disconnect response from ME
394  *
395  * @dev: the device structure
396  * @rs: disconnect response bus message
397  */
398 static void mei_hbm_cl_disconnect_res(struct mei_device *dev,
399                 struct hbm_client_connect_response *rs)
400 {
401         struct mei_cl *cl;
402         struct mei_cl_cb *pos = NULL, *next = NULL;
403
404         dev_dbg(&dev->pdev->dev,
405                         "disconnect_response:\n"
406                         "ME Client = %d\n"
407                         "Host Client = %d\n"
408                         "Status = %d\n",
409                         rs->me_addr,
410                         rs->host_addr,
411                         rs->status);
412
413         list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
414                 cl = pos->cl;
415
416                 if (!cl) {
417                         list_del(&pos->list);
418                         return;
419                 }
420
421                 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
422                 if (mei_hbm_cl_addr_equal(cl, rs)) {
423                         list_del(&pos->list);
424                         if (!rs->status)
425                                 cl->state = MEI_FILE_DISCONNECTED;
426
427                         cl->status = 0;
428                         cl->timer_count = 0;
429                         break;
430                 }
431         }
432 }
433
434 /**
435  * mei_hbm_cl_connect_req - send connection request to specific me client
436  *
437  * @dev: the device structure
438  * @cl: a client to connect to
439  *
440  * returns -EIO on write failure
441  */
442 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
443 {
444         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
445         const size_t len = sizeof(struct hbm_client_connect_request);
446
447         mei_hbm_hdr(mei_hdr, len);
448         mei_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, dev->wr_msg.data, len);
449
450         return mei_write_message(dev, mei_hdr,  dev->wr_msg.data);
451 }
452
453 /**
454  * mei_hbm_cl_connect_res - connect resposne from the ME
455  *
456  * @dev: the device structure
457  * @rs: connect response bus message
458  */
459 static void mei_hbm_cl_connect_res(struct mei_device *dev,
460                 struct hbm_client_connect_response *rs)
461 {
462
463         struct mei_cl *cl;
464         struct mei_cl_cb *pos = NULL, *next = NULL;
465
466         dev_dbg(&dev->pdev->dev,
467                         "connect_response:\n"
468                         "ME Client = %d\n"
469                         "Host Client = %d\n"
470                         "Status = %d\n",
471                         rs->me_addr,
472                         rs->host_addr,
473                         rs->status);
474
475         /* if WD or iamthif client treat specially */
476
477         if (is_treat_specially_client(&dev->wd_cl, rs)) {
478                 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
479                 mei_watchdog_register(dev);
480
481                 return;
482         }
483
484         if (is_treat_specially_client(&dev->iamthif_cl, rs)) {
485                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
486                 return;
487         }
488         list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
489
490                 cl = pos->cl;
491                 if (!cl) {
492                         list_del(&pos->list);
493                         return;
494                 }
495                 if (pos->fop_type == MEI_FOP_IOCTL) {
496                         if (is_treat_specially_client(cl, rs)) {
497                                 list_del(&pos->list);
498                                 cl->status = 0;
499                                 cl->timer_count = 0;
500                                 break;
501                         }
502                 }
503         }
504 }
505
506
507 /**
508  * mei_hbm_fw_disconnect_req - disconnect request initiated by me
509  *  host sends disoconnect response
510  *
511  * @dev: the device structure.
512  * @disconnect_req: disconnect request bus message from the me
513  */
514 static void mei_hbm_fw_disconnect_req(struct mei_device *dev,
515                 struct hbm_client_connect_request *disconnect_req)
516 {
517         struct mei_cl *cl, *next;
518         const size_t len = sizeof(struct hbm_client_connect_response);
519
520         list_for_each_entry_safe(cl, next, &dev->file_list, link) {
521                 if (mei_hbm_cl_addr_equal(cl, disconnect_req)) {
522                         dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
523                                         disconnect_req->host_addr,
524                                         disconnect_req->me_addr);
525                         cl->state = MEI_FILE_DISCONNECTED;
526                         cl->timer_count = 0;
527                         if (cl == &dev->wd_cl)
528                                 dev->wd_pending = false;
529                         else if (cl == &dev->iamthif_cl)
530                                 dev->iamthif_timer = 0;
531
532                         /* prepare disconnect response */
533                         mei_hbm_hdr(&dev->wr_ext_msg.hdr, len);
534                         mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD,
535                                          dev->wr_ext_msg.data, len);
536                         break;
537                 }
538         }
539 }
540
541
542 /**
543  * mei_hbm_dispatch - bottom half read routine after ISR to
544  * handle the read bus message cmd processing.
545  *
546  * @dev: the device structure
547  * @mei_hdr: header of bus message
548  */
549 void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
550 {
551         struct mei_bus_message *mei_msg;
552         struct mei_me_client *me_client;
553         struct hbm_host_version_response *version_res;
554         struct hbm_client_connect_response *connect_res;
555         struct hbm_client_connect_response *disconnect_res;
556         struct hbm_client_connect_request *disconnect_req;
557         struct hbm_flow_control *flow_control;
558         struct hbm_props_response *props_res;
559         struct hbm_host_enum_response *enum_res;
560
561         /* read the message to our buffer */
562         BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
563         mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
564         mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
565
566         switch (mei_msg->hbm_cmd) {
567         case HOST_START_RES_CMD:
568                 version_res = (struct hbm_host_version_response *)mei_msg;
569                 if (!version_res->host_version_supported) {
570                         dev->version = version_res->me_max_version;
571                         dev_dbg(&dev->pdev->dev, "version mismatch.\n");
572
573                         dev->hbm_state = MEI_HBM_STOP;
574                         mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
575                                                 dev->wr_msg.data);
576                         mei_write_message(dev, &dev->wr_msg.hdr,
577                                         dev->wr_msg.data);
578
579                         return;
580                 }
581
582                 dev->version.major_version = HBM_MAJOR_VERSION;
583                 dev->version.minor_version = HBM_MINOR_VERSION;
584                 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
585                     dev->hbm_state == MEI_HBM_START) {
586                         dev->init_clients_timer = 0;
587                         mei_hbm_enum_clients_req(dev);
588                 } else {
589                         dev_err(&dev->pdev->dev, "reset: wrong host start response\n");
590                         mei_reset(dev, 1);
591                         return;
592                 }
593
594                 wake_up_interruptible(&dev->wait_recvd_msg);
595                 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
596                 break;
597
598         case CLIENT_CONNECT_RES_CMD:
599                 connect_res = (struct hbm_client_connect_response *) mei_msg;
600                 mei_hbm_cl_connect_res(dev, connect_res);
601                 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
602                 wake_up(&dev->wait_recvd_msg);
603                 break;
604
605         case CLIENT_DISCONNECT_RES_CMD:
606                 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
607                 mei_hbm_cl_disconnect_res(dev, disconnect_res);
608                 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
609                 wake_up(&dev->wait_recvd_msg);
610                 break;
611
612         case MEI_FLOW_CONTROL_CMD:
613                 flow_control = (struct hbm_flow_control *) mei_msg;
614                 mei_hbm_cl_flow_control_res(dev, flow_control);
615                 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
616                 break;
617
618         case HOST_CLIENT_PROPERTIES_RES_CMD:
619                 props_res = (struct hbm_props_response *)mei_msg;
620                 me_client = &dev->me_clients[dev->me_client_presentation_num];
621
622                 if (props_res->status || !dev->me_clients) {
623                         dev_err(&dev->pdev->dev, "reset: properties response hbm wrong status.\n");
624                         mei_reset(dev, 1);
625                         return;
626                 }
627
628                 if (me_client->client_id != props_res->address) {
629                         dev_err(&dev->pdev->dev, "reset: host properties response address mismatch\n");
630                         mei_reset(dev, 1);
631                         return;
632                 }
633
634                 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
635                     dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
636                         dev_err(&dev->pdev->dev, "reset: unexpected properties response\n");
637                         mei_reset(dev, 1);
638
639                         return;
640                 }
641
642                 me_client->props = props_res->client_properties;
643                 dev->me_client_index++;
644                 dev->me_client_presentation_num++;
645
646                 /* request property for the next client */
647                 mei_hbm_prop_req(dev);
648
649                 break;
650
651         case HOST_ENUM_RES_CMD:
652                 enum_res = (struct hbm_host_enum_response *) mei_msg;
653                 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
654                 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
655                     dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
656                                 dev->init_clients_timer = 0;
657                                 mei_hbm_me_cl_allocate(dev);
658                                 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
659
660                                 /* first property reqeust */
661                                 mei_hbm_prop_req(dev);
662                 } else {
663                         dev_err(&dev->pdev->dev, "reset: unexpected enumeration response hbm.\n");
664                         mei_reset(dev, 1);
665                         return;
666                 }
667                 break;
668
669         case HOST_STOP_RES_CMD:
670
671                 if (dev->hbm_state != MEI_HBM_STOP)
672                         dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n");
673                 dev->dev_state = MEI_DEV_DISABLED;
674                 dev_info(&dev->pdev->dev, "reset: FW stop response.\n");
675                 mei_reset(dev, 1);
676                 break;
677
678         case CLIENT_DISCONNECT_REQ_CMD:
679                 /* search for client */
680                 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
681                 mei_hbm_fw_disconnect_req(dev, disconnect_req);
682                 break;
683
684         case ME_STOP_REQ_CMD:
685
686                 dev->hbm_state = MEI_HBM_STOP;
687                 mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
688                                         dev->wr_ext_msg.data);
689                 break;
690         default:
691                 BUG();
692                 break;
693
694         }
695 }
696