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