Merge 3.5-rc7 into char-misc-next.
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / misc / mei / init.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/delay.h>
21
22 #include "mei_dev.h"
23 #include "hw.h"
24 #include "interface.h"
25 #include <linux/mei.h>
26
27 const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
28                                                 0xa8, 0x46, 0xe0, 0xff, 0x65,
29                                                 0x81, 0x4c);
30
31 /**
32  * mei_io_list_init - Sets up a queue list.
33  *
34  * @list: An instance io list structure
35  * @dev: the device structure
36  */
37 void mei_io_list_init(struct mei_io_list *list)
38 {
39         /* initialize our queue list */
40         INIT_LIST_HEAD(&list->mei_cb.cb_list);
41 }
42
43 /**
44  * mei_io_list_flush - removes list entry belonging to cl.
45  *
46  * @list:  An instance of our list structure
47  * @cl: private data of the file object
48  */
49 void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
50 {
51         struct mei_cl_cb *pos;
52         struct mei_cl_cb *next;
53
54         list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
55                 if (pos->file_private) {
56                         struct mei_cl *cl_tmp;
57                         cl_tmp = (struct mei_cl *)pos->file_private;
58                         if (mei_cl_cmp_id(cl, cl_tmp))
59                                 list_del(&pos->cb_list);
60                 }
61         }
62 }
63 /**
64  * mei_cl_flush_queues - flushes queue lists belonging to cl.
65  *
66  * @dev: the device structure
67  * @cl: private data of the file object
68  */
69 int mei_cl_flush_queues(struct mei_cl *cl)
70 {
71         if (!cl || !cl->dev)
72                 return -EINVAL;
73
74         dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
75         mei_io_list_flush(&cl->dev->read_list, cl);
76         mei_io_list_flush(&cl->dev->write_list, cl);
77         mei_io_list_flush(&cl->dev->write_waiting_list, cl);
78         mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
79         mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
80         mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
81         mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
82         return 0;
83 }
84
85
86
87 /**
88  * mei_reset_iamthif_params - initializes mei device iamthif
89  *
90  * @dev: the device structure
91  */
92 static void mei_reset_iamthif_params(struct mei_device *dev)
93 {
94         /* reset iamthif parameters. */
95         dev->iamthif_current_cb = NULL;
96         dev->iamthif_msg_buf_size = 0;
97         dev->iamthif_msg_buf_index = 0;
98         dev->iamthif_canceled = false;
99         dev->iamthif_ioctl = false;
100         dev->iamthif_state = MEI_IAMTHIF_IDLE;
101         dev->iamthif_timer = 0;
102 }
103
104 /**
105  * init_mei_device - allocates and initializes the mei device structure
106  *
107  * @pdev: The pci device structure
108  *
109  * returns The mei_device_device pointer on success, NULL on failure.
110  */
111 struct mei_device *mei_device_init(struct pci_dev *pdev)
112 {
113         struct mei_device *dev;
114
115         dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
116         if (!dev)
117                 return NULL;
118
119         /* setup our list array */
120         INIT_LIST_HEAD(&dev->file_list);
121         INIT_LIST_HEAD(&dev->wd_cl.link);
122         INIT_LIST_HEAD(&dev->iamthif_cl.link);
123         mutex_init(&dev->device_lock);
124         init_waitqueue_head(&dev->wait_recvd_msg);
125         init_waitqueue_head(&dev->wait_stop_wd);
126         dev->mei_state = MEI_INITIALIZING;
127         dev->iamthif_state = MEI_IAMTHIF_IDLE;
128         dev->wd_interface_reg = false;
129
130
131         mei_io_list_init(&dev->read_list);
132         mei_io_list_init(&dev->write_list);
133         mei_io_list_init(&dev->write_waiting_list);
134         mei_io_list_init(&dev->ctrl_wr_list);
135         mei_io_list_init(&dev->ctrl_rd_list);
136         mei_io_list_init(&dev->amthi_cmd_list);
137         mei_io_list_init(&dev->amthi_read_complete_list);
138         dev->pdev = pdev;
139         return dev;
140 }
141
142 /**
143  * mei_hw_init - initializes host and fw to start work.
144  *
145  * @dev: the device structure
146  *
147  * returns 0 on success, <0 on failure.
148  */
149 int mei_hw_init(struct mei_device *dev)
150 {
151         int err = 0;
152         int ret;
153
154         mutex_lock(&dev->device_lock);
155
156         dev->host_hw_state = mei_hcsr_read(dev);
157         dev->me_hw_state = mei_mecsr_read(dev);
158         dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
159             dev->host_hw_state, dev->me_hw_state);
160
161         /* acknowledge interrupt and stop interupts */
162         if ((dev->host_hw_state & H_IS) == H_IS)
163                 mei_reg_write(dev, H_CSR, dev->host_hw_state);
164
165         /* Doesn't change in runtime */
166         dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24;
167
168         dev->recvd_msg = false;
169         dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
170
171         mei_reset(dev, 1);
172
173         dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
174             dev->host_hw_state, dev->me_hw_state);
175
176         /* wait for ME to turn on ME_RDY */
177         if (!dev->recvd_msg) {
178                 mutex_unlock(&dev->device_lock);
179                 err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
180                         dev->recvd_msg, MEI_INTEROP_TIMEOUT);
181                 mutex_lock(&dev->device_lock);
182         }
183
184         if (err <= 0 && !dev->recvd_msg) {
185                 dev->mei_state = MEI_DISABLED;
186                 dev_dbg(&dev->pdev->dev,
187                         "wait_event_interruptible_timeout failed"
188                         "on wait for ME to turn on ME_RDY.\n");
189                 ret = -ENODEV;
190                 goto out;
191         }
192
193         if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
194               ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
195                 dev->mei_state = MEI_DISABLED;
196                 dev_dbg(&dev->pdev->dev,
197                         "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
198                         dev->host_hw_state, dev->me_hw_state);
199
200                 if (!(dev->host_hw_state & H_RDY))
201                         dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n");
202
203                 if (!(dev->me_hw_state & ME_RDY_HRA))
204                         dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
205
206                 dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
207                 ret = -ENODEV;
208                 goto out;
209         }
210
211         if (dev->version.major_version != HBM_MAJOR_VERSION ||
212             dev->version.minor_version != HBM_MINOR_VERSION) {
213                 dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
214                 ret = -ENODEV;
215                 goto out;
216         }
217
218         dev->recvd_msg = false;
219         dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
220             dev->host_hw_state, dev->me_hw_state);
221         dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
222         dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
223         dev_dbg(&dev->pdev->dev, "MEI  start success.\n");
224         ret = 0;
225
226 out:
227         mutex_unlock(&dev->device_lock);
228         return ret;
229 }
230
231 /**
232  * mei_hw_reset - resets fw via mei csr register.
233  *
234  * @dev: the device structure
235  * @interrupts_enabled: if interrupt should be enabled after reset.
236  */
237 static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled)
238 {
239         dev->host_hw_state |= (H_RST | H_IG);
240
241         if (interrupts_enabled)
242                 mei_enable_interrupts(dev);
243         else
244                 mei_disable_interrupts(dev);
245 }
246
247 /**
248  * mei_reset - resets host and fw.
249  *
250  * @dev: the device structure
251  * @interrupts_enabled: if interrupt should be enabled after reset.
252  */
253 void mei_reset(struct mei_device *dev, int interrupts_enabled)
254 {
255         struct mei_cl *cl_pos = NULL;
256         struct mei_cl *cl_next = NULL;
257         struct mei_cl_cb *cb_pos = NULL;
258         struct mei_cl_cb *cb_next = NULL;
259         bool unexpected;
260
261         if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
262                 dev->need_reset = true;
263                 return;
264         }
265
266         unexpected = (dev->mei_state != MEI_INITIALIZING &&
267                         dev->mei_state != MEI_DISABLED &&
268                         dev->mei_state != MEI_POWER_DOWN &&
269                         dev->mei_state != MEI_POWER_UP);
270
271         dev->host_hw_state = mei_hcsr_read(dev);
272
273         dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n",
274             dev->host_hw_state);
275
276         mei_hw_reset(dev, interrupts_enabled);
277
278         dev->host_hw_state &= ~H_RST;
279         dev->host_hw_state |= H_IG;
280
281         mei_hcsr_set(dev);
282
283         dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
284             dev->host_hw_state);
285
286         dev->need_reset = false;
287
288         if (dev->mei_state != MEI_INITIALIZING) {
289                 if (dev->mei_state != MEI_DISABLED &&
290                     dev->mei_state != MEI_POWER_DOWN)
291                         dev->mei_state = MEI_RESETING;
292
293                 list_for_each_entry_safe(cl_pos,
294                                 cl_next, &dev->file_list, link) {
295                         cl_pos->state = MEI_FILE_DISCONNECTED;
296                         cl_pos->mei_flow_ctrl_creds = 0;
297                         cl_pos->read_cb = NULL;
298                         cl_pos->timer_count = 0;
299                 }
300                 /* remove entry if already in list */
301                 dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
302                 mei_remove_client_from_file_list(dev,
303                                 dev->wd_cl.host_client_id);
304
305                 mei_remove_client_from_file_list(dev,
306                                 dev->iamthif_cl.host_client_id);
307
308                 mei_reset_iamthif_params(dev);
309                 dev->extra_write_index = 0;
310         }
311
312         dev->me_clients_num = 0;
313         dev->rd_msg_hdr = 0;
314         dev->stop = false;
315         dev->wd_pending = false;
316
317         /* update the state of the registers after reset */
318         dev->host_hw_state = mei_hcsr_read(dev);
319         dev->me_hw_state = mei_mecsr_read(dev);
320
321         dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
322             dev->host_hw_state, dev->me_hw_state);
323
324         if (unexpected)
325                 dev_warn(&dev->pdev->dev, "unexpected reset.\n");
326
327         /* Wake up all readings so they can be interrupted */
328         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
329                 if (waitqueue_active(&cl_pos->rx_wait)) {
330                         dev_dbg(&dev->pdev->dev, "Waking up client!\n");
331                         wake_up_interruptible(&cl_pos->rx_wait);
332                 }
333         }
334         /* remove all waiting requests */
335         list_for_each_entry_safe(cb_pos, cb_next,
336                         &dev->write_list.mei_cb.cb_list, cb_list) {
337                 list_del(&cb_pos->cb_list);
338                 mei_free_cb_private(cb_pos);
339         }
340 }
341
342
343
344 /**
345  * host_start_message - mei host sends start message.
346  *
347  * @dev: the device structure
348  *
349  * returns none.
350  */
351 void mei_host_start_message(struct mei_device *dev)
352 {
353         struct mei_msg_hdr *mei_hdr;
354         struct hbm_host_version_request *host_start_req;
355
356         /* host start message */
357         mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
358         mei_hdr->host_addr = 0;
359         mei_hdr->me_addr = 0;
360         mei_hdr->length = sizeof(struct hbm_host_version_request);
361         mei_hdr->msg_complete = 1;
362         mei_hdr->reserved = 0;
363
364         host_start_req =
365             (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
366         memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
367         host_start_req->hbm_cmd = HOST_START_REQ_CMD;
368         host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
369         host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
370         dev->recvd_msg = false;
371         if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
372                                        mei_hdr->length)) {
373                 dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
374                 dev->mei_state = MEI_RESETING;
375                 mei_reset(dev, 1);
376         }
377         dev->init_clients_state = MEI_START_MESSAGE;
378         dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
379         return ;
380 }
381
382 /**
383  * host_enum_clients_message - host sends enumeration client request message.
384  *
385  * @dev: the device structure
386  *
387  * returns none.
388  */
389 void mei_host_enum_clients_message(struct mei_device *dev)
390 {
391         struct mei_msg_hdr *mei_hdr;
392         struct hbm_host_enum_request *host_enum_req;
393         mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
394         /* enumerate clients */
395         mei_hdr->host_addr = 0;
396         mei_hdr->me_addr = 0;
397         mei_hdr->length = sizeof(struct hbm_host_enum_request);
398         mei_hdr->msg_complete = 1;
399         mei_hdr->reserved = 0;
400
401         host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
402         memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
403         host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
404         if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
405                                 mei_hdr->length)) {
406                 dev->mei_state = MEI_RESETING;
407                 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
408                 mei_reset(dev, 1);
409         }
410         dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
411         dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
412         return;
413 }
414
415
416 /**
417  * allocate_me_clients_storage - allocates storage for me clients
418  *
419  * @dev: the device structure
420  *
421  * returns none.
422  */
423 void mei_allocate_me_clients_storage(struct mei_device *dev)
424 {
425         struct mei_me_client *clients;
426         int b;
427
428         /* count how many ME clients we have */
429         for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
430                 dev->me_clients_num++;
431
432         if (dev->me_clients_num <= 0)
433                 return ;
434
435
436         if (dev->me_clients != NULL) {
437                 kfree(dev->me_clients);
438                 dev->me_clients = NULL;
439         }
440         dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
441                 dev->me_clients_num * sizeof(struct mei_me_client));
442         /* allocate storage for ME clients representation */
443         clients = kcalloc(dev->me_clients_num,
444                         sizeof(struct mei_me_client), GFP_KERNEL);
445         if (!clients) {
446                 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
447                 dev->mei_state = MEI_RESETING;
448                 mei_reset(dev, 1);
449                 return ;
450         }
451         dev->me_clients = clients;
452         return ;
453 }
454 /**
455  * host_client_properties - reads properties for client
456  *
457  * @dev: the device structure
458  *
459  * returns:
460  *      < 0 - Error.
461  *  = 0 - no more clients.
462  *  = 1 - still have clients to send properties request.
463  */
464 int mei_host_client_properties(struct mei_device *dev)
465 {
466         struct mei_msg_hdr *mei_header;
467         struct hbm_props_request *host_cli_req;
468         int b;
469         u8 client_num = dev->me_client_presentation_num;
470
471         b = dev->me_client_index;
472         b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
473         if (b < MEI_CLIENTS_MAX) {
474                 dev->me_clients[client_num].client_id = b;
475                 dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
476                 mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
477                 mei_header->host_addr = 0;
478                 mei_header->me_addr = 0;
479                 mei_header->length = sizeof(struct hbm_props_request);
480                 mei_header->msg_complete = 1;
481                 mei_header->reserved = 0;
482
483                 host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
484
485                 memset(host_cli_req, 0, sizeof(struct hbm_props_request));
486
487                 host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
488                 host_cli_req->address = b;
489
490                 if (mei_write_message(dev, mei_header,
491                                 (unsigned char *)host_cli_req,
492                                 mei_header->length)) {
493                         dev->mei_state = MEI_RESETING;
494                         dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
495                         mei_reset(dev, 1);
496                         return -EIO;
497                 }
498
499                 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
500                 dev->me_client_index = b;
501                 return 1;
502         }
503
504         return 0;
505 }
506
507 /**
508  * mei_init_file_private - initializes private file structure.
509  *
510  * @priv: private file structure to be initialized
511  * @file: the file structure
512  */
513 void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
514 {
515         memset(priv, 0, sizeof(struct mei_cl));
516         init_waitqueue_head(&priv->wait);
517         init_waitqueue_head(&priv->rx_wait);
518         init_waitqueue_head(&priv->tx_wait);
519         INIT_LIST_HEAD(&priv->link);
520         priv->reading_state = MEI_IDLE;
521         priv->writing_state = MEI_IDLE;
522         priv->dev = dev;
523 }
524
525 int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
526 {
527         int i, res = -1;
528
529         for (i = 0; i < dev->me_clients_num; ++i)
530                 if (uuid_le_cmp(cuuid,
531                                 dev->me_clients[i].props.protocol_name) == 0) {
532                         res = i;
533                         break;
534                 }
535
536         return res;
537 }
538
539
540 /**
541  * mei_find_me_client_update_filext - searches for ME client guid
542  *                       sets client_id in mei_file_private if found
543  * @dev: the device structure
544  * @priv: private file structure to set client_id in
545  * @cguid: searched guid of ME client
546  * @client_id: id of host client to be set in file private structure
547  *
548  * returns ME client index
549  */
550 u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
551                                 const uuid_le *cguid, u8 client_id)
552 {
553         int i;
554
555         if (!dev || !priv || !cguid)
556                 return 0;
557
558         /* check for valid client id */
559         i = mei_find_me_client_index(dev, *cguid);
560         if (i >= 0) {
561                 priv->me_client_id = dev->me_clients[i].client_id;
562                 priv->state = MEI_FILE_CONNECTING;
563                 priv->host_client_id = client_id;
564
565                 list_add_tail(&priv->link, &dev->file_list);
566                 return (u8)i;
567         }
568
569         return 0;
570 }
571
572 /**
573  * host_init_iamthif - mei initialization iamthif client.
574  *
575  * @dev: the device structure
576  *
577  */
578 void mei_host_init_iamthif(struct mei_device *dev)
579 {
580         u8 i;
581         unsigned char *msg_buf;
582
583         mei_cl_init(&dev->iamthif_cl, dev);
584         dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
585
586         /* find ME amthi client */
587         i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl,
588                             &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
589         if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) {
590                 dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
591                 return;
592         }
593
594         /* Assign iamthif_mtu to the value received from ME  */
595
596         dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
597         dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
598                         dev->me_clients[i].props.max_msg_length);
599
600         kfree(dev->iamthif_msg_buf);
601         dev->iamthif_msg_buf = NULL;
602
603         /* allocate storage for ME message buffer */
604         msg_buf = kcalloc(dev->iamthif_mtu,
605                         sizeof(unsigned char), GFP_KERNEL);
606         if (!msg_buf) {
607                 dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
608                 return;
609         }
610
611         dev->iamthif_msg_buf = msg_buf;
612
613         if (mei_connect(dev, &dev->iamthif_cl)) {
614                 dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
615                 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
616                 dev->iamthif_cl.host_client_id = 0;
617         } else {
618                 dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
619         }
620 }
621
622 /**
623  * mei_alloc_file_private - allocates a private file structure and sets it up.
624  * @file: the file structure
625  *
626  * returns  The allocated file or NULL on failure
627  */
628 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
629 {
630         struct mei_cl *cl;
631
632         cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
633         if (!cl)
634                 return NULL;
635
636         mei_cl_init(cl, dev);
637
638         return cl;
639 }
640
641
642
643 /**
644  * mei_disconnect_host_client - sends disconnect message to fw from host client.
645  *
646  * @dev: the device structure
647  * @cl: private data of the file object
648  *
649  * Locking: called under "dev->device_lock" lock
650  *
651  * returns 0 on success, <0 on failure.
652  */
653 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
654 {
655         int rets, err;
656         long timeout = 15;      /* 15 seconds */
657         struct mei_cl_cb *cb;
658
659         if (!dev || !cl)
660                 return -ENODEV;
661
662         if (cl->state != MEI_FILE_DISCONNECTING)
663                 return 0;
664
665         cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
666         if (!cb)
667                 return -ENOMEM;
668
669         INIT_LIST_HEAD(&cb->cb_list);
670         cb->file_private = cl;
671         cb->major_file_operations = MEI_CLOSE;
672         if (dev->mei_host_buffer_is_empty) {
673                 dev->mei_host_buffer_is_empty = false;
674                 if (mei_disconnect(dev, cl)) {
675                         rets = -ENODEV;
676                         dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n");
677                         goto free;
678                 }
679                 mdelay(10); /* Wait for hardware disconnection ready */
680                 list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
681         } else {
682                 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
683                 list_add_tail(&cb->cb_list,
684                                 &dev->ctrl_wr_list.mei_cb.cb_list);
685         }
686         mutex_unlock(&dev->device_lock);
687
688         err = wait_event_timeout(dev->wait_recvd_msg,
689                  (MEI_FILE_DISCONNECTED == cl->state),
690                  timeout * HZ);
691
692         mutex_lock(&dev->device_lock);
693         if (MEI_FILE_DISCONNECTED == cl->state) {
694                 rets = 0;
695                 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
696         } else {
697                 rets = -ENODEV;
698                 if (MEI_FILE_DISCONNECTED != cl->state)
699                         dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
700
701                 if (err)
702                         dev_dbg(&dev->pdev->dev,
703                                         "wait failed disconnect err=%08x\n",
704                                         err);
705
706                 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
707         }
708
709         mei_io_list_flush(&dev->ctrl_rd_list, cl);
710         mei_io_list_flush(&dev->ctrl_wr_list, cl);
711 free:
712         mei_free_cb_private(cb);
713         return rets;
714 }
715
716 /**
717  * mei_remove_client_from_file_list -
718  *      removes file private data from device file list
719  *
720  * @dev: the device structure
721  * @host_client_id: host client id to be removed
722  */
723 void mei_remove_client_from_file_list(struct mei_device *dev,
724                                        u8 host_client_id)
725 {
726         struct mei_cl *cl_pos = NULL;
727         struct mei_cl *cl_next = NULL;
728         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
729                 if (host_client_id == cl_pos->host_client_id) {
730                         dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
731                                         cl_pos->host_client_id,
732                                         cl_pos->me_client_id);
733                         list_del_init(&cl_pos->link);
734                         break;
735                 }
736         }
737 }