packaging: release out (3.8.3)
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / misc / mei / amthif.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/kernel.h>
18 #include <linux/fs.h>
19 #include <linux/errno.h>
20 #include <linux/types.h>
21 #include <linux/fcntl.h>
22 #include <linux/aio.h>
23 #include <linux/pci.h>
24 #include <linux/init.h>
25 #include <linux/ioctl.h>
26 #include <linux/cdev.h>
27 #include <linux/list.h>
28 #include <linux/delay.h>
29 #include <linux/sched.h>
30 #include <linux/uuid.h>
31 #include <linux/jiffies.h>
32 #include <linux/uaccess.h>
33
34
35 #include "mei_dev.h"
36 #include "hw.h"
37 #include <linux/mei.h>
38 #include "interface.h"
39
40 const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
41                                                 0xa8, 0x46, 0xe0, 0xff, 0x65,
42                                                 0x81, 0x4c);
43
44 /**
45  * mei_amthif_reset_params - initializes mei device iamthif
46  *
47  * @dev: the device structure
48  */
49 void mei_amthif_reset_params(struct mei_device *dev)
50 {
51         /* reset iamthif parameters. */
52         dev->iamthif_current_cb = NULL;
53         dev->iamthif_msg_buf_size = 0;
54         dev->iamthif_msg_buf_index = 0;
55         dev->iamthif_canceled = false;
56         dev->iamthif_ioctl = false;
57         dev->iamthif_state = MEI_IAMTHIF_IDLE;
58         dev->iamthif_timer = 0;
59 }
60
61 /**
62  * mei_amthif_host_init_ - mei initialization amthif client.
63  *
64  * @dev: the device structure
65  *
66  */
67 void mei_amthif_host_init(struct mei_device *dev)
68 {
69         int i;
70         unsigned char *msg_buf;
71
72         mei_cl_init(&dev->iamthif_cl, dev);
73         dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
74
75         /* find ME amthi client */
76         i = mei_me_cl_link(dev, &dev->iamthif_cl,
77                             &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
78         if (i < 0) {
79                 dev_info(&dev->pdev->dev, "failed to find iamthif client.\n");
80                 return;
81         }
82
83         /* Assign iamthif_mtu to the value received from ME  */
84
85         dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
86         dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
87                         dev->me_clients[i].props.max_msg_length);
88
89         kfree(dev->iamthif_msg_buf);
90         dev->iamthif_msg_buf = NULL;
91
92         /* allocate storage for ME message buffer */
93         msg_buf = kcalloc(dev->iamthif_mtu,
94                         sizeof(unsigned char), GFP_KERNEL);
95         if (!msg_buf) {
96                 dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
97                 return;
98         }
99
100         dev->iamthif_msg_buf = msg_buf;
101
102         if (mei_connect(dev, &dev->iamthif_cl)) {
103                 dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
104                 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
105                 dev->iamthif_cl.host_client_id = 0;
106         } else {
107                 dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT;
108         }
109 }
110
111 /**
112  * mei_amthif_find_read_list_entry - finds a amthilist entry for current file
113  *
114  * @dev: the device structure
115  * @file: pointer to file object
116  *
117  * returns   returned a list entry on success, NULL on failure.
118  */
119 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
120                                                 struct file *file)
121 {
122         struct mei_cl_cb *pos = NULL;
123         struct mei_cl_cb *next = NULL;
124
125         list_for_each_entry_safe(pos, next,
126                                 &dev->amthif_rd_complete_list.list, list) {
127                 if (pos->cl && pos->cl == &dev->iamthif_cl &&
128                         pos->file_object == file)
129                         return pos;
130         }
131         return NULL;
132 }
133
134
135 /**
136  * mei_amthif_read - read data from AMTHIF client
137  *
138  * @dev: the device structure
139  * @if_num:  minor number
140  * @file: pointer to file object
141  * @*ubuf: pointer to user data in user space
142  * @length: data length to read
143  * @offset: data read offset
144  *
145  * Locking: called under "dev->device_lock" lock
146  *
147  * returns
148  *  returned data length on success,
149  *  zero if no data to read,
150  *  negative on failure.
151  */
152 int mei_amthif_read(struct mei_device *dev, struct file *file,
153                char __user *ubuf, size_t length, loff_t *offset)
154 {
155         int rets;
156         int wait_ret;
157         struct mei_cl_cb *cb = NULL;
158         struct mei_cl *cl = file->private_data;
159         unsigned long timeout;
160         int i;
161
162         /* Only Posible if we are in timeout */
163         if (!cl || cl != &dev->iamthif_cl) {
164                 dev_dbg(&dev->pdev->dev, "bad file ext.\n");
165                 return -ETIMEDOUT;
166         }
167
168         i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
169
170         if (i < 0) {
171                 dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
172                 return -ENODEV;
173         }
174         dev_dbg(&dev->pdev->dev, "checking amthi data\n");
175         cb = mei_amthif_find_read_list_entry(dev, file);
176
177         /* Check for if we can block or not*/
178         if (cb == NULL && file->f_flags & O_NONBLOCK)
179                 return -EAGAIN;
180
181
182         dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
183         while (cb == NULL) {
184                 /* unlock the Mutex */
185                 mutex_unlock(&dev->device_lock);
186
187                 wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
188                         (cb = mei_amthif_find_read_list_entry(dev, file)));
189
190                 /* Locking again the Mutex */
191                 mutex_lock(&dev->device_lock);
192
193                 if (wait_ret)
194                         return -ERESTARTSYS;
195
196                 dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
197         }
198
199
200         dev_dbg(&dev->pdev->dev, "Got amthi data\n");
201         dev->iamthif_timer = 0;
202
203         if (cb) {
204                 timeout = cb->read_time +
205                         mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
206                 dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
207                                 timeout);
208
209                 if  (time_after(jiffies, timeout)) {
210                         dev_dbg(&dev->pdev->dev, "amthi Time out\n");
211                         /* 15 sec for the message has expired */
212                         list_del(&cb->list);
213                         rets = -ETIMEDOUT;
214                         goto free;
215                 }
216         }
217         /* if the whole message will fit remove it from the list */
218         if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
219                 list_del(&cb->list);
220         else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
221                 /* end of the message has been reached */
222                 list_del(&cb->list);
223                 rets = 0;
224                 goto free;
225         }
226                 /* else means that not full buffer will be read and do not
227                  * remove message from deletion list
228                  */
229
230         dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
231             cb->response_buffer.size);
232         dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx);
233
234         /* length is being turncated to PAGE_SIZE, however,
235          * the buf_idx may point beyond */
236         length = min_t(size_t, length, (cb->buf_idx - *offset));
237
238         if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
239                 rets = -EFAULT;
240         else {
241                 rets = length;
242                 if ((*offset + length) < cb->buf_idx) {
243                         *offset += length;
244                         goto out;
245                 }
246         }
247 free:
248         dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
249         *offset = 0;
250         mei_io_cb_free(cb);
251 out:
252         return rets;
253 }
254
255 /**
256  * mei_amthif_send_cmd - send amthif command to the ME
257  *
258  * @dev: the device structure
259  * @cb: mei call back struct
260  *
261  * returns 0 on success, <0 on failure.
262  *
263  */
264 static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
265 {
266         struct mei_msg_hdr mei_hdr;
267         int ret;
268
269         if (!dev || !cb)
270                 return -ENODEV;
271
272         dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
273
274         dev->iamthif_state = MEI_IAMTHIF_WRITING;
275         dev->iamthif_current_cb = cb;
276         dev->iamthif_file_object = cb->file_object;
277         dev->iamthif_canceled = false;
278         dev->iamthif_ioctl = true;
279         dev->iamthif_msg_buf_size = cb->request_buffer.size;
280         memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
281                cb->request_buffer.size);
282
283         ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
284         if (ret < 0)
285                 return ret;
286
287         if (ret && dev->mei_host_buffer_is_empty) {
288                 ret = 0;
289                 dev->mei_host_buffer_is_empty = false;
290                 if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
291                         mei_hdr.length = mei_hbuf_max_data(dev);
292                         mei_hdr.msg_complete = 0;
293                 } else {
294                         mei_hdr.length = cb->request_buffer.size;
295                         mei_hdr.msg_complete = 1;
296                 }
297
298                 mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
299                 mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
300                 mei_hdr.reserved = 0;
301                 dev->iamthif_msg_buf_index += mei_hdr.length;
302                 if (mei_write_message(dev, &mei_hdr,
303                                         (unsigned char *)(dev->iamthif_msg_buf),
304                                         mei_hdr.length))
305                         return -ENODEV;
306
307                 if (mei_hdr.msg_complete) {
308                         if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
309                                 return -ENODEV;
310                         dev->iamthif_flow_control_pending = true;
311                         dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
312                         dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
313                         dev->iamthif_current_cb = cb;
314                         dev->iamthif_file_object = cb->file_object;
315                         list_add_tail(&cb->list, &dev->write_waiting_list.list);
316                 } else {
317                         dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n");
318                         list_add_tail(&cb->list, &dev->write_list.list);
319                 }
320         } else {
321                 if (!(dev->mei_host_buffer_is_empty))
322                         dev_dbg(&dev->pdev->dev, "host buffer is not empty");
323
324                 dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
325                 list_add_tail(&cb->list, &dev->write_list.list);
326         }
327         return 0;
328 }
329
330 /**
331  * mei_amthif_write - write amthif data to amthif client
332  *
333  * @dev: the device structure
334  * @cb: mei call back struct
335  *
336  * returns 0 on success, <0 on failure.
337  *
338  */
339 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
340 {
341         int ret;
342
343         if (!dev || !cb)
344                 return -ENODEV;
345
346         ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
347         if (ret)
348                 return ret;
349
350         cb->fop_type = MEI_FOP_IOCTL;
351
352         if (!list_empty(&dev->amthif_cmd_list.list) ||
353             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
354                 dev_dbg(&dev->pdev->dev,
355                         "amthif state = %d\n", dev->iamthif_state);
356                 dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
357                 list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
358                 return 0;
359         }
360         return mei_amthif_send_cmd(dev, cb);
361 }
362 /**
363  * mei_amthif_run_next_cmd
364  *
365  * @dev: the device structure
366  *
367  * returns 0 on success, <0 on failure.
368  */
369 void mei_amthif_run_next_cmd(struct mei_device *dev)
370 {
371         struct mei_cl_cb *pos = NULL;
372         struct mei_cl_cb *next = NULL;
373         int status;
374
375         if (!dev)
376                 return;
377
378         dev->iamthif_msg_buf_size = 0;
379         dev->iamthif_msg_buf_index = 0;
380         dev->iamthif_canceled = false;
381         dev->iamthif_ioctl = true;
382         dev->iamthif_state = MEI_IAMTHIF_IDLE;
383         dev->iamthif_timer = 0;
384         dev->iamthif_file_object = NULL;
385
386         dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
387
388         list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
389                 list_del(&pos->list);
390
391                 if (pos->cl && pos->cl == &dev->iamthif_cl) {
392                         status = mei_amthif_send_cmd(dev, pos);
393                         if (status) {
394                                 dev_dbg(&dev->pdev->dev,
395                                         "amthi write failed status = %d\n",
396                                                 status);
397                                 return;
398                         }
399                         break;
400                 }
401         }
402 }
403
404
405 unsigned int mei_amthif_poll(struct mei_device *dev,
406                 struct file *file, poll_table *wait)
407 {
408         unsigned int mask = 0;
409         mutex_unlock(&dev->device_lock);
410         poll_wait(file, &dev->iamthif_cl.wait, wait);
411         mutex_lock(&dev->device_lock);
412         if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
413                 dev->iamthif_file_object == file) {
414                 mask |= (POLLIN | POLLRDNORM);
415                 dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
416                 mei_amthif_run_next_cmd(dev);
417         }
418         return mask;
419 }
420
421
422
423 /**
424  * mei_amthif_irq_process_completed - processes completed iamthif operation.
425  *
426  * @dev: the device structure.
427  * @slots: free slots.
428  * @cb_pos: callback block.
429  * @cl: private data of the file object.
430  * @cmpl_list: complete list.
431  *
432  * returns 0, OK; otherwise, error.
433  */
434 int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
435                         struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
436 {
437         struct mei_msg_hdr *mei_hdr;
438         struct mei_cl *cl = cb->cl;
439         size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
440         size_t msg_slots = mei_data2slots(len);
441
442         mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
443         mei_hdr->host_addr = cl->host_client_id;
444         mei_hdr->me_addr = cl->me_client_id;
445         mei_hdr->reserved = 0;
446
447         if (*slots >= msg_slots) {
448                 mei_hdr->length = len;
449                 mei_hdr->msg_complete = 1;
450         /* Split the message only if we can write the whole host buffer */
451         } else if (*slots == dev->hbuf_depth) {
452                 msg_slots = *slots;
453                 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
454                 mei_hdr->length = len;
455                 mei_hdr->msg_complete = 0;
456         } else {
457                 /* wait for next time the host buffer is empty */
458                 return 0;
459         }
460
461         dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
462                         mei_hdr->length, mei_hdr->msg_complete);
463
464         *slots -=  msg_slots;
465         if (mei_write_message(dev, mei_hdr,
466                 dev->iamthif_msg_buf + dev->iamthif_msg_buf_index,
467                 mei_hdr->length)) {
468                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
469                         cl->status = -ENODEV;
470                         list_del(&cb->list);
471                         return -ENODEV;
472         }
473
474         if (mei_flow_ctrl_reduce(dev, cl))
475                 return -ENODEV;
476
477         dev->iamthif_msg_buf_index += mei_hdr->length;
478         cl->status = 0;
479
480         if (mei_hdr->msg_complete) {
481                 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
482                 dev->iamthif_flow_control_pending = true;
483
484                 /* save iamthif cb sent to amthi client */
485                 cb->buf_idx = dev->iamthif_msg_buf_index;
486                 dev->iamthif_current_cb = cb;
487
488                 list_move_tail(&cb->list, &dev->write_waiting_list.list);
489         }
490
491
492         return 0;
493 }
494
495 /**
496  * mei_amthif_irq_read_message - read routine after ISR to
497  *                      handle the read amthi message
498  *
499  * @complete_list: An instance of our list structure
500  * @dev: the device structure
501  * @mei_hdr: header of amthi message
502  *
503  * returns 0 on success, <0 on failure.
504  */
505 int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
506                 struct mei_device *dev, struct mei_msg_hdr *mei_hdr)
507 {
508         struct mei_cl_cb *cb;
509         unsigned char *buffer;
510
511         BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
512         BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
513
514         buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
515         BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
516
517         mei_read_slots(dev, buffer, mei_hdr->length);
518
519         dev->iamthif_msg_buf_index += mei_hdr->length;
520
521         if (!mei_hdr->msg_complete)
522                 return 0;
523
524         dev_dbg(&dev->pdev->dev,
525                         "amthi_message_buffer_index =%d\n",
526                         mei_hdr->length);
527
528         dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
529         if (!dev->iamthif_current_cb)
530                 return -ENODEV;
531
532         cb = dev->iamthif_current_cb;
533         dev->iamthif_current_cb = NULL;
534
535         if (!cb->cl)
536                 return -ENODEV;
537
538         dev->iamthif_stall_timer = 0;
539         cb->buf_idx = dev->iamthif_msg_buf_index;
540         cb->read_time = jiffies;
541         if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
542                 /* found the iamthif cb */
543                 dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
544                 dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
545                 list_add_tail(&cb->list, &complete_list->list);
546         }
547         return 0;
548 }
549
550 /**
551  * mei_amthif_irq_read - prepares to read amthif data.
552  *
553  * @dev: the device structure.
554  * @slots: free slots.
555  *
556  * returns 0, OK; otherwise, error.
557  */
558 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
559 {
560
561         if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
562                         + sizeof(struct hbm_flow_control))) {
563                 return -EMSGSIZE;
564         }
565         *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
566         if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
567                 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
568                 return -EIO;
569         }
570
571         dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
572         dev->iamthif_state = MEI_IAMTHIF_READING;
573         dev->iamthif_flow_control_pending = false;
574         dev->iamthif_msg_buf_index = 0;
575         dev->iamthif_msg_buf_size = 0;
576         dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
577         dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
578         return 0;
579 }
580
581 /**
582  * mei_amthif_complete - complete amthif callback.
583  *
584  * @dev: the device structure.
585  * @cb_pos: callback block.
586  */
587 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
588 {
589         if (dev->iamthif_canceled != 1) {
590                 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
591                 dev->iamthif_stall_timer = 0;
592                 memcpy(cb->response_buffer.data,
593                                 dev->iamthif_msg_buf,
594                                 dev->iamthif_msg_buf_index);
595                 list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
596                 dev_dbg(&dev->pdev->dev, "amthi read completed\n");
597                 dev->iamthif_timer = jiffies;
598                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
599                                 dev->iamthif_timer);
600         } else {
601                 mei_amthif_run_next_cmd(dev);
602         }
603
604         dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
605         wake_up_interruptible(&dev->iamthif_cl.wait);
606 }
607
608 /**
609  * mei_clear_list - removes all callbacks associated with file
610  *              from mei_cb_list
611  *
612  * @dev: device structure.
613  * @file: file structure
614  * @mei_cb_list: callbacks list
615  *
616  * mei_clear_list is called to clear resources associated with file
617  * when application calls close function or Ctrl-C was pressed
618  *
619  * returns true if callback removed from the list, false otherwise
620  */
621 static bool mei_clear_list(struct mei_device *dev,
622                 const struct file *file, struct list_head *mei_cb_list)
623 {
624         struct mei_cl_cb *cb_pos = NULL;
625         struct mei_cl_cb *cb_next = NULL;
626         bool removed = false;
627
628         /* list all list member */
629         list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
630                 /* check if list member associated with a file */
631                 if (file == cb_pos->file_object) {
632                         /* remove member from the list */
633                         list_del(&cb_pos->list);
634                         /* check if cb equal to current iamthif cb */
635                         if (dev->iamthif_current_cb == cb_pos) {
636                                 dev->iamthif_current_cb = NULL;
637                                 /* send flow control to iamthif client */
638                                 mei_send_flow_control(dev, &dev->iamthif_cl);
639                         }
640                         /* free all allocated buffers */
641                         mei_io_cb_free(cb_pos);
642                         cb_pos = NULL;
643                         removed = true;
644                 }
645         }
646         return removed;
647 }
648
649 /**
650  * mei_clear_lists - removes all callbacks associated with file
651  *
652  * @dev: device structure
653  * @file: file structure
654  *
655  * mei_clear_lists is called to clear resources associated with file
656  * when application calls close function or Ctrl-C was pressed
657  *
658  * returns true if callback removed from the list, false otherwise
659  */
660 static bool mei_clear_lists(struct mei_device *dev, struct file *file)
661 {
662         bool removed = false;
663
664         /* remove callbacks associated with a file */
665         mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
666         if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
667                 removed = true;
668
669         mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
670
671         if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
672                 removed = true;
673
674         if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
675                 removed = true;
676
677         if (mei_clear_list(dev, file, &dev->write_list.list))
678                 removed = true;
679
680         /* check if iamthif_current_cb not NULL */
681         if (dev->iamthif_current_cb && !removed) {
682                 /* check file and iamthif current cb association */
683                 if (dev->iamthif_current_cb->file_object == file) {
684                         /* remove cb */
685                         mei_io_cb_free(dev->iamthif_current_cb);
686                         dev->iamthif_current_cb = NULL;
687                         removed = true;
688                 }
689         }
690         return removed;
691 }
692
693 /**
694 * mei_amthif_release - the release function
695 *
696 *  @inode: pointer to inode structure
697 *  @file: pointer to file structure
698 *
699 *  returns 0 on success, <0 on error
700 */
701 int mei_amthif_release(struct mei_device *dev, struct file *file)
702 {
703         if (dev->open_handle_count > 0)
704                 dev->open_handle_count--;
705
706         if (dev->iamthif_file_object == file &&
707             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
708
709                 dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
710                     dev->iamthif_state);
711                 dev->iamthif_canceled = true;
712                 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
713                         dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
714                         mei_amthif_run_next_cmd(dev);
715                 }
716         }
717
718         if (mei_clear_lists(dev, file))
719                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
720
721         return 0;
722 }