mei: implement power gating isolation hbm layer
[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/export.h>
18 #include <linux/pci.h>
19 #include <linux/sched.h>
20 #include <linux/wait.h>
21 #include <linux/mei.h>
22
23 #include "mei_dev.h"
24 #include "hbm.h"
25 #include "client.h"
26
27 static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
28 {
29 #define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
30         switch (status) {
31         MEI_CL_CS(SUCCESS);
32         MEI_CL_CS(NOT_FOUND);
33         MEI_CL_CS(ALREADY_STARTED);
34         MEI_CL_CS(OUT_OF_RESOURCES);
35         MEI_CL_CS(MESSAGE_SMALL);
36         default: return "unknown";
37         }
38 #undef MEI_CL_CCS
39 }
40
41 /**
42  * mei_cl_conn_status_to_errno - convert client connect response
43  * status to error code
44  *
45  * @status: client connect response status
46  *
47  * returns corresponding error code
48  */
49 static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
50 {
51         switch (status) {
52         case MEI_CL_CONN_SUCCESS:          return 0;
53         case MEI_CL_CONN_NOT_FOUND:        return -ENOTTY;
54         case MEI_CL_CONN_ALREADY_STARTED:  return -EBUSY;
55         case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY;
56         case MEI_CL_CONN_MESSAGE_SMALL:    return -EINVAL;
57         default:                           return -EINVAL;
58         }
59 }
60
61 /**
62  * mei_hbm_me_cl_allocate - allocates storage for me clients
63  *
64  * @dev: the device structure
65  *
66  * returns 0 on success -ENOMEM on allocation failure
67  */
68 static int mei_hbm_me_cl_allocate(struct mei_device *dev)
69 {
70         struct mei_me_client *clients;
71         int b;
72
73         dev->me_clients_num = 0;
74         dev->me_client_presentation_num = 0;
75         dev->me_client_index = 0;
76
77         /* count how many ME clients we have */
78         for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
79                 dev->me_clients_num++;
80
81         if (dev->me_clients_num == 0)
82                 return 0;
83
84         kfree(dev->me_clients);
85         dev->me_clients = NULL;
86
87         dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
88                 dev->me_clients_num * sizeof(struct mei_me_client));
89         /* allocate storage for ME clients representation */
90         clients = kcalloc(dev->me_clients_num,
91                         sizeof(struct mei_me_client), GFP_KERNEL);
92         if (!clients) {
93                 dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
94                 return -ENOMEM;
95         }
96         dev->me_clients = clients;
97         return 0;
98 }
99
100 /**
101  * mei_hbm_cl_hdr - construct client hbm header
102  *
103  * @cl: - client
104  * @hbm_cmd: host bus message command
105  * @buf: buffer for cl header
106  * @len: buffer length
107  */
108 static inline
109 void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
110 {
111         struct mei_hbm_cl_cmd *cmd = buf;
112
113         memset(cmd, 0, len);
114
115         cmd->hbm_cmd = hbm_cmd;
116         cmd->host_addr = cl->host_client_id;
117         cmd->me_addr = cl->me_client_id;
118 }
119
120 /**
121  * mei_hbm_cl_addr_equal - tells if they have the same address
122  *
123  * @cl: - client
124  * @buf: buffer with cl header
125  *
126  * returns true if addresses are the same
127  */
128 static inline
129 bool mei_hbm_cl_addr_equal(struct mei_cl *cl, void *buf)
130 {
131         struct mei_hbm_cl_cmd *cmd = buf;
132         return cl->host_client_id == cmd->host_addr &&
133                 cl->me_client_id == cmd->me_addr;
134 }
135
136
137 /**
138  * mei_hbm_idle - set hbm to idle state
139  *
140  * @dev: the device structure
141  */
142 void mei_hbm_idle(struct mei_device *dev)
143 {
144         dev->init_clients_timer = 0;
145         dev->hbm_state = MEI_HBM_IDLE;
146 }
147
148 int mei_hbm_start_wait(struct mei_device *dev)
149 {
150         int ret;
151         if (dev->hbm_state > MEI_HBM_START)
152                 return 0;
153
154         mutex_unlock(&dev->device_lock);
155         ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
156                         dev->hbm_state == MEI_HBM_IDLE ||
157                         dev->hbm_state >= MEI_HBM_STARTED,
158                         mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
159         mutex_lock(&dev->device_lock);
160
161         if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
162                 dev->hbm_state = MEI_HBM_IDLE;
163                 dev_err(&dev->pdev->dev, "waiting for mei start failed\n");
164                 return -ETIME;
165         }
166         return 0;
167 }
168
169 /**
170  * mei_hbm_start_req - sends start request message.
171  *
172  * @dev: the device structure
173  *
174  * returns 0 on success and < 0 on failure
175  */
176 int mei_hbm_start_req(struct mei_device *dev)
177 {
178         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
179         struct hbm_host_version_request *start_req;
180         const size_t len = sizeof(struct hbm_host_version_request);
181         int ret;
182
183         mei_hbm_hdr(mei_hdr, len);
184
185         /* host start message */
186         start_req = (struct hbm_host_version_request *)dev->wr_msg.data;
187         memset(start_req, 0, len);
188         start_req->hbm_cmd = HOST_START_REQ_CMD;
189         start_req->host_version.major_version = HBM_MAJOR_VERSION;
190         start_req->host_version.minor_version = HBM_MINOR_VERSION;
191
192         dev->hbm_state = MEI_HBM_IDLE;
193         ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
194         if (ret) {
195                 dev_err(&dev->pdev->dev, "version message write failed: ret = %d\n",
196                         ret);
197                 return ret;
198         }
199
200         dev->hbm_state = MEI_HBM_START;
201         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
202         return 0;
203 }
204
205 /*
206  * mei_hbm_enum_clients_req - sends enumeration client request message.
207  *
208  * @dev: the device structure
209  *
210  * returns 0 on success and < 0 on failure
211  */
212 static int mei_hbm_enum_clients_req(struct mei_device *dev)
213 {
214         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
215         struct hbm_host_enum_request *enum_req;
216         const size_t len = sizeof(struct hbm_host_enum_request);
217         int ret;
218
219         /* enumerate clients */
220         mei_hbm_hdr(mei_hdr, len);
221
222         enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data;
223         memset(enum_req, 0, len);
224         enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
225
226         ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
227         if (ret) {
228                 dev_err(&dev->pdev->dev, "enumeration request write failed: ret = %d.\n",
229                         ret);
230                 return ret;
231         }
232         dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
233         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
234         return 0;
235 }
236
237 /**
238  * mei_hbm_prop_req - request property for a single client
239  *
240  * @dev: the device structure
241  *
242  * returns 0 on success and < 0 on failure
243  */
244
245 static int mei_hbm_prop_req(struct mei_device *dev)
246 {
247
248         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
249         struct hbm_props_request *prop_req;
250         const size_t len = sizeof(struct hbm_props_request);
251         unsigned long next_client_index;
252         unsigned long client_num;
253         int ret;
254
255         client_num = dev->me_client_presentation_num;
256
257         next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
258                                           dev->me_client_index);
259
260         /* We got all client properties */
261         if (next_client_index == MEI_CLIENTS_MAX) {
262                 dev->hbm_state = MEI_HBM_STARTED;
263                 schedule_work(&dev->init_work);
264
265                 return 0;
266         }
267
268         dev->me_clients[client_num].client_id = next_client_index;
269         dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
270
271         mei_hbm_hdr(mei_hdr, len);
272         prop_req = (struct hbm_props_request *)dev->wr_msg.data;
273
274         memset(prop_req, 0, sizeof(struct hbm_props_request));
275
276
277         prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
278         prop_req->address = next_client_index;
279
280         ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
281         if (ret) {
282                 dev_err(&dev->pdev->dev, "properties request write failed: ret = %d\n",
283                         ret);
284                 return ret;
285         }
286
287         dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
288         dev->me_client_index = next_client_index;
289
290         return 0;
291 }
292
293 /*
294  * mei_hbm_pg - sends pg command
295  *
296  * @dev: the device structure
297  * @pg_cmd: the pg command code
298  *
299  * This function returns -EIO on write failure
300  */
301 int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
302 {
303         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
304         struct hbm_power_gate *req;
305         const size_t len = sizeof(struct hbm_power_gate);
306         int ret;
307
308         mei_hbm_hdr(mei_hdr, len);
309
310         req = (struct hbm_power_gate *)dev->wr_msg.data;
311         memset(req, 0, len);
312         req->hbm_cmd = pg_cmd;
313
314         ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
315         if (ret)
316                 dev_err(&dev->pdev->dev, "power gate command write failed.\n");
317         return ret;
318 }
319 EXPORT_SYMBOL_GPL(mei_hbm_pg);
320
321 /**
322  * mei_hbm_stop_req - send stop request message
323  *
324  * @dev - mei device
325  * @cl: client info
326  *
327  * This function returns -EIO on write failure
328  */
329 static int mei_hbm_stop_req(struct mei_device *dev)
330 {
331         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
332         struct hbm_host_stop_request *req =
333                         (struct hbm_host_stop_request *)dev->wr_msg.data;
334         const size_t len = sizeof(struct hbm_host_stop_request);
335
336         mei_hbm_hdr(mei_hdr, len);
337
338         memset(req, 0, len);
339         req->hbm_cmd = HOST_STOP_REQ_CMD;
340         req->reason = DRIVER_STOP_REQUEST;
341
342         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
343 }
344
345 /**
346  * mei_hbm_cl_flow_control_req - sends flow control request.
347  *
348  * @dev: the device structure
349  * @cl: client info
350  *
351  * This function returns -EIO on write failure
352  */
353 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
354 {
355         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
356         const size_t len = sizeof(struct hbm_flow_control);
357
358         mei_hbm_hdr(mei_hdr, len);
359         mei_hbm_cl_hdr(cl, MEI_FLOW_CONTROL_CMD, dev->wr_msg.data, len);
360
361         cl_dbg(dev, cl, "sending flow control\n");
362
363         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
364 }
365
366 /**
367  * mei_hbm_add_single_flow_creds - adds single buffer credentials.
368  *
369  * @dev: the device structure
370  * @flow: flow control.
371  *
372  * return 0 on success, < 0 otherwise
373  */
374 static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
375                                   struct hbm_flow_control *flow)
376 {
377         struct mei_me_client *me_cl;
378         int id;
379
380         id = mei_me_cl_by_id(dev, flow->me_addr);
381         if (id < 0) {
382                 dev_err(&dev->pdev->dev, "no such me client %d\n",
383                         flow->me_addr);
384                 return id;
385         }
386
387         me_cl = &dev->me_clients[id];
388         if (me_cl->props.single_recv_buf) {
389                 me_cl->mei_flow_ctrl_creds++;
390                 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
391                     flow->me_addr);
392                 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
393                     me_cl->mei_flow_ctrl_creds);
394         } else {
395                 BUG();  /* error in flow control */
396         }
397
398         return 0;
399 }
400
401 /**
402  * mei_hbm_cl_flow_control_res - flow control response from me
403  *
404  * @dev: the device structure
405  * @flow_control: flow control response bus message
406  */
407 static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
408                 struct hbm_flow_control *flow_control)
409 {
410         struct mei_cl *cl;
411
412         if (!flow_control->host_addr) {
413                 /* single receive buffer */
414                 mei_hbm_add_single_flow_creds(dev, flow_control);
415                 return;
416         }
417
418         /* normal connection */
419         list_for_each_entry(cl, &dev->file_list, link) {
420                 if (mei_hbm_cl_addr_equal(cl, flow_control)) {
421                         cl->mei_flow_ctrl_creds++;
422                         dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
423                                 flow_control->host_addr, flow_control->me_addr);
424                         dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
425                                     cl->mei_flow_ctrl_creds);
426                                 break;
427                 }
428         }
429 }
430
431
432 /**
433  * mei_hbm_cl_disconnect_req - sends disconnect message to fw.
434  *
435  * @dev: the device structure
436  * @cl: a client to disconnect from
437  *
438  * This function returns -EIO on write failure
439  */
440 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
441 {
442         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
443         const size_t len = sizeof(struct hbm_client_connect_request);
444
445         mei_hbm_hdr(mei_hdr, len);
446         mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, dev->wr_msg.data, len);
447
448         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
449 }
450
451 /**
452  * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
453  *
454  * @dev: the device structure
455  * @cl: a client to disconnect from
456  *
457  * This function returns -EIO on write failure
458  */
459 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
460 {
461         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
462         const size_t len = sizeof(struct hbm_client_connect_response);
463
464         mei_hbm_hdr(mei_hdr, len);
465         mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, dev->wr_msg.data, len);
466
467         return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
468 }
469
470 /**
471  * mei_hbm_cl_disconnect_res - disconnect response from ME
472  *
473  * @dev: the device structure
474  * @rs: disconnect response bus message
475  */
476 static void mei_hbm_cl_disconnect_res(struct mei_device *dev,
477                 struct hbm_client_connect_response *rs)
478 {
479         struct mei_cl *cl;
480         struct mei_cl_cb *cb, *next;
481
482         dev_dbg(&dev->pdev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
483                         rs->me_addr, rs->host_addr, rs->status);
484
485         list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
486                 cl = cb->cl;
487
488                 /* this should not happen */
489                 if (WARN_ON(!cl)) {
490                         list_del(&cb->list);
491                         return;
492                 }
493
494                 if (mei_hbm_cl_addr_equal(cl, rs)) {
495                         list_del(&cb->list);
496                         if (rs->status == MEI_CL_DISCONN_SUCCESS)
497                                 cl->state = MEI_FILE_DISCONNECTED;
498
499                         cl->status = 0;
500                         cl->timer_count = 0;
501                         break;
502                 }
503         }
504 }
505
506 /**
507  * mei_hbm_cl_connect_req - send connection request to specific me client
508  *
509  * @dev: the device structure
510  * @cl: a client to connect to
511  *
512  * returns -EIO on write failure
513  */
514 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
515 {
516         struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
517         const size_t len = sizeof(struct hbm_client_connect_request);
518
519         mei_hbm_hdr(mei_hdr, len);
520         mei_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, dev->wr_msg.data, len);
521
522         return mei_write_message(dev, mei_hdr,  dev->wr_msg.data);
523 }
524
525 /**
526  * mei_hbm_cl_connect_res - connect response from the ME
527  *
528  * @dev: the device structure
529  * @rs: connect response bus message
530  */
531 static void mei_hbm_cl_connect_res(struct mei_device *dev,
532                 struct hbm_client_connect_response *rs)
533 {
534
535         struct mei_cl *cl;
536         struct mei_cl_cb *cb, *next;
537
538         dev_dbg(&dev->pdev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
539                         rs->me_addr, rs->host_addr,
540                         mei_cl_conn_status_str(rs->status));
541
542         cl = NULL;
543
544         list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
545
546                 cl = cb->cl;
547                 /* this should not happen */
548                 if (WARN_ON(!cl)) {
549                         list_del_init(&cb->list);
550                         continue;
551                 }
552
553                 if (cb->fop_type !=  MEI_FOP_CONNECT)
554                         continue;
555
556                 if (mei_hbm_cl_addr_equal(cl, rs)) {
557                         list_del(&cb->list);
558                         break;
559                 }
560         }
561
562         if (!cl)
563                 return;
564
565         cl->timer_count = 0;
566         if (rs->status == MEI_CL_CONN_SUCCESS)
567                 cl->state = MEI_FILE_CONNECTED;
568         else
569                 cl->state = MEI_FILE_DISCONNECTED;
570         cl->status = mei_cl_conn_status_to_errno(rs->status);
571 }
572
573
574 /**
575  * mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware
576  *  host sends disconnect response
577  *
578  * @dev: the device structure.
579  * @disconnect_req: disconnect request bus message from the me
580  *
581  * returns -ENOMEM on allocation failure
582  */
583 static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
584                 struct hbm_client_connect_request *disconnect_req)
585 {
586         struct mei_cl *cl;
587         struct mei_cl_cb *cb;
588
589         list_for_each_entry(cl, &dev->file_list, link) {
590                 if (mei_hbm_cl_addr_equal(cl, disconnect_req)) {
591                         dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
592                                         disconnect_req->host_addr,
593                                         disconnect_req->me_addr);
594                         cl->state = MEI_FILE_DISCONNECTED;
595                         cl->timer_count = 0;
596
597                         cb = mei_io_cb_init(cl, NULL);
598                         if (!cb)
599                                 return -ENOMEM;
600                         cb->fop_type = MEI_FOP_DISCONNECT_RSP;
601                         cl_dbg(dev, cl, "add disconnect response as first\n");
602                         list_add(&cb->list, &dev->ctrl_wr_list.list);
603
604                         break;
605                 }
606         }
607         return 0;
608 }
609
610
611 /**
612  * mei_hbm_version_is_supported - checks whether the driver can
613  *     support the hbm version of the device
614  *
615  * @dev: the device structure
616  * returns true if driver can support hbm version of the device
617  */
618 bool mei_hbm_version_is_supported(struct mei_device *dev)
619 {
620         return  (dev->version.major_version < HBM_MAJOR_VERSION) ||
621                 (dev->version.major_version == HBM_MAJOR_VERSION &&
622                  dev->version.minor_version <= HBM_MINOR_VERSION);
623 }
624
625 /**
626  * mei_hbm_dispatch - bottom half read routine after ISR to
627  * handle the read bus message cmd processing.
628  *
629  * @dev: the device structure
630  * @mei_hdr: header of bus message
631  *
632  * returns 0 on success and < 0 on failure
633  */
634 int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
635 {
636         struct mei_bus_message *mei_msg;
637         struct mei_me_client *me_client;
638         struct hbm_host_version_response *version_res;
639         struct hbm_client_connect_response *connect_res;
640         struct hbm_client_connect_response *disconnect_res;
641         struct hbm_client_connect_request *disconnect_req;
642         struct hbm_flow_control *flow_control;
643         struct hbm_props_response *props_res;
644         struct hbm_host_enum_response *enum_res;
645
646         /* read the message to our buffer */
647         BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
648         mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
649         mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
650
651         /* ignore spurious message and prevent reset nesting
652          * hbm is put to idle during system reset
653          */
654         if (dev->hbm_state == MEI_HBM_IDLE) {
655                 dev_dbg(&dev->pdev->dev, "hbm: state is idle ignore spurious messages\n");
656                 return 0;
657         }
658
659         switch (mei_msg->hbm_cmd) {
660         case HOST_START_RES_CMD:
661                 dev_dbg(&dev->pdev->dev, "hbm: start: response message received.\n");
662
663                 dev->init_clients_timer = 0;
664
665                 version_res = (struct hbm_host_version_response *)mei_msg;
666
667                 dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
668                                 HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
669                                 version_res->me_max_version.major_version,
670                                 version_res->me_max_version.minor_version);
671
672                 if (version_res->host_version_supported) {
673                         dev->version.major_version = HBM_MAJOR_VERSION;
674                         dev->version.minor_version = HBM_MINOR_VERSION;
675                 } else {
676                         dev->version.major_version =
677                                 version_res->me_max_version.major_version;
678                         dev->version.minor_version =
679                                 version_res->me_max_version.minor_version;
680                 }
681
682                 if (!mei_hbm_version_is_supported(dev)) {
683                         dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n");
684
685                         dev->hbm_state = MEI_HBM_STOPPED;
686                         if (mei_hbm_stop_req(dev)) {
687                                 dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
688                                 return -EIO;
689                         }
690                         break;
691                 }
692
693                 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
694                     dev->hbm_state != MEI_HBM_START) {
695                         dev_err(&dev->pdev->dev, "hbm: start: state mismatch, [%d, %d]\n",
696                                 dev->dev_state, dev->hbm_state);
697                         return -EPROTO;
698                 }
699
700                 dev->hbm_state = MEI_HBM_STARTED;
701
702                 if (mei_hbm_enum_clients_req(dev)) {
703                         dev_err(&dev->pdev->dev, "hbm: start: failed to send enumeration request\n");
704                         return -EIO;
705                 }
706
707                 wake_up_interruptible(&dev->wait_recvd_msg);
708                 break;
709
710         case CLIENT_CONNECT_RES_CMD:
711                 dev_dbg(&dev->pdev->dev, "hbm: client connect response: message received.\n");
712
713                 connect_res = (struct hbm_client_connect_response *) mei_msg;
714                 mei_hbm_cl_connect_res(dev, connect_res);
715                 wake_up(&dev->wait_recvd_msg);
716                 break;
717
718         case CLIENT_DISCONNECT_RES_CMD:
719                 dev_dbg(&dev->pdev->dev, "hbm: client disconnect response: message received.\n");
720
721                 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
722                 mei_hbm_cl_disconnect_res(dev, disconnect_res);
723                 wake_up(&dev->wait_recvd_msg);
724                 break;
725
726         case MEI_FLOW_CONTROL_CMD:
727                 dev_dbg(&dev->pdev->dev, "hbm: client flow control response: message received.\n");
728
729                 flow_control = (struct hbm_flow_control *) mei_msg;
730                 mei_hbm_cl_flow_control_res(dev, flow_control);
731                 break;
732
733         case MEI_PG_ISOLATION_ENTRY_RES_CMD:
734                 dev_dbg(&dev->pdev->dev, "power gate isolation entry response received\n");
735                 if (waitqueue_active(&dev->wait_pg))
736                         wake_up(&dev->wait_pg);
737                 break;
738
739         case MEI_PG_ISOLATION_EXIT_REQ_CMD:
740                 dev_dbg(&dev->pdev->dev, "power gate isolation exit request received\n");
741                 if (waitqueue_active(&dev->wait_pg))
742                         wake_up(&dev->wait_pg);
743                 break;
744
745         case HOST_CLIENT_PROPERTIES_RES_CMD:
746                 dev_dbg(&dev->pdev->dev, "hbm: properties response: message received.\n");
747
748                 dev->init_clients_timer = 0;
749
750                 if (dev->me_clients == NULL) {
751                         dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n");
752                         return -EPROTO;
753                 }
754
755                 props_res = (struct hbm_props_response *)mei_msg;
756                 me_client = &dev->me_clients[dev->me_client_presentation_num];
757
758                 if (props_res->status) {
759                         dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n",
760                                 props_res->status);
761                         return -EPROTO;
762                 }
763
764                 if (me_client->client_id != props_res->address) {
765                         dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n",
766                                 me_client->client_id, props_res->address);
767                         return -EPROTO;
768                 }
769
770                 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
771                     dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
772                         dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
773                                 dev->dev_state, dev->hbm_state);
774                         return -EPROTO;
775                 }
776
777                 me_client->props = props_res->client_properties;
778                 dev->me_client_index++;
779                 dev->me_client_presentation_num++;
780
781                 /* request property for the next client */
782                 if (mei_hbm_prop_req(dev))
783                         return -EIO;
784
785                 break;
786
787         case HOST_ENUM_RES_CMD:
788                 dev_dbg(&dev->pdev->dev, "hbm: enumeration response: message received\n");
789
790                 dev->init_clients_timer = 0;
791
792                 enum_res = (struct hbm_host_enum_response *) mei_msg;
793                 BUILD_BUG_ON(sizeof(dev->me_clients_map)
794                                 < sizeof(enum_res->valid_addresses));
795                 memcpy(dev->me_clients_map, enum_res->valid_addresses,
796                         sizeof(enum_res->valid_addresses));
797
798                 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
799                     dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
800                         dev_err(&dev->pdev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
801                                 dev->dev_state, dev->hbm_state);
802                         return -EPROTO;
803                 }
804
805                 if (mei_hbm_me_cl_allocate(dev)) {
806                         dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n");
807                         return -ENOMEM;
808                 }
809
810                 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
811
812                 /* first property request */
813                 if (mei_hbm_prop_req(dev))
814                         return -EIO;
815
816                 break;
817
818         case HOST_STOP_RES_CMD:
819                 dev_dbg(&dev->pdev->dev, "hbm: stop response: message received\n");
820
821                 dev->init_clients_timer = 0;
822
823                 if (dev->hbm_state != MEI_HBM_STOPPED) {
824                         dev_err(&dev->pdev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
825                                 dev->dev_state, dev->hbm_state);
826                         return -EPROTO;
827                 }
828
829                 dev->dev_state = MEI_DEV_POWER_DOWN;
830                 dev_info(&dev->pdev->dev, "hbm: stop response: resetting.\n");
831                 /* force the reset */
832                 return -EPROTO;
833                 break;
834
835         case CLIENT_DISCONNECT_REQ_CMD:
836                 dev_dbg(&dev->pdev->dev, "hbm: disconnect request: message received\n");
837
838                 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
839                 mei_hbm_fw_disconnect_req(dev, disconnect_req);
840                 break;
841
842         case ME_STOP_REQ_CMD:
843                 dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n");
844                 dev->hbm_state = MEI_HBM_STOPPED;
845                 if (mei_hbm_stop_req(dev)) {
846                         dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
847                         return -EIO;
848                 }
849                 break;
850         default:
851                 BUG();
852                 break;
853
854         }
855         return 0;
856 }
857