e7ba8801d2b4afe01494e1e8982fdf775b7dcfa3
[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_completed - processes completed iamthif operation.
440  *
441  * @dev: the device structure.
442  * @slots: free slots.
443  * @cb_pos: callback block.
444  * @cl: private data of the file object.
445  * @cmpl_list: complete list.
446  *
447  * returns 0, OK; otherwise, error.
448  */
449 int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
450                                   s32 *slots, struct mei_cl_cb *cmpl_list)
451 {
452         struct mei_device *dev = cl->dev;
453         struct mei_msg_hdr mei_hdr;
454         size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
455         u32 msg_slots = mei_data2slots(len);
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         if (*slots >= msg_slots) {
473                 mei_hdr.length = len;
474                 mei_hdr.msg_complete = 1;
475         /* Split the message only if we can write the whole host buffer */
476         } else if (*slots == dev->hbuf_depth) {
477                 msg_slots = *slots;
478                 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
479                 mei_hdr.length = len;
480                 mei_hdr.msg_complete = 0;
481         } else {
482                 /* wait for next time the host buffer is empty */
483                 return 0;
484         }
485
486         dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
487
488         *slots -=  msg_slots;
489         rets = mei_write_message(dev, &mei_hdr,
490                         dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
491         if (rets) {
492                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
493                 cl->status = rets;
494                 list_del(&cb->list);
495                 return rets;
496         }
497
498         if (mei_cl_flow_ctrl_reduce(cl))
499                 return -EIO;
500
501         dev->iamthif_msg_buf_index += mei_hdr.length;
502         cl->status = 0;
503
504         if (mei_hdr.msg_complete) {
505                 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
506                 dev->iamthif_flow_control_pending = true;
507
508                 /* save iamthif cb sent to amthif client */
509                 cb->buf_idx = dev->iamthif_msg_buf_index;
510                 dev->iamthif_current_cb = cb;
511
512                 list_move_tail(&cb->list, &dev->write_waiting_list.list);
513         }
514
515
516         return 0;
517 }
518
519 /**
520  * mei_amthif_irq_read_message - read routine after ISR to
521  *                      handle the read amthif message
522  *
523  * @dev: the device structure
524  * @mei_hdr: header of amthif message
525  * @complete_list: An instance of our list structure
526  *
527  * returns 0 on success, <0 on failure.
528  */
529 int mei_amthif_irq_read_msg(struct mei_device *dev,
530                             struct mei_msg_hdr *mei_hdr,
531                             struct mei_cl_cb *complete_list)
532 {
533         struct mei_cl_cb *cb;
534         unsigned char *buffer;
535
536         BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
537         BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
538
539         buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
540         BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
541
542         mei_read_slots(dev, buffer, mei_hdr->length);
543
544         dev->iamthif_msg_buf_index += mei_hdr->length;
545
546         if (!mei_hdr->msg_complete)
547                 return 0;
548
549         dev_dbg(&dev->pdev->dev, "amthif_message_buffer_index =%d\n",
550                         mei_hdr->length);
551
552         dev_dbg(&dev->pdev->dev, "completed amthif read.\n ");
553         if (!dev->iamthif_current_cb)
554                 return -ENODEV;
555
556         cb = dev->iamthif_current_cb;
557         dev->iamthif_current_cb = NULL;
558
559         if (!cb->cl)
560                 return -ENODEV;
561
562         dev->iamthif_stall_timer = 0;
563         cb->buf_idx = dev->iamthif_msg_buf_index;
564         cb->read_time = jiffies;
565         if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
566                 /* found the iamthif cb */
567                 dev_dbg(&dev->pdev->dev, "complete the amthif read cb.\n ");
568                 dev_dbg(&dev->pdev->dev, "add the amthif read cb to complete.\n ");
569                 list_add_tail(&cb->list, &complete_list->list);
570         }
571         return 0;
572 }
573
574 /**
575  * mei_amthif_irq_read - prepares to read amthif data.
576  *
577  * @dev: the device structure.
578  * @slots: free slots.
579  *
580  * returns 0, OK; otherwise, error.
581  */
582 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
583 {
584         u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
585
586         if (*slots < msg_slots)
587                 return -EMSGSIZE;
588
589         *slots -= msg_slots;
590
591         if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
592                 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
593                 return -EIO;
594         }
595
596         dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
597         dev->iamthif_state = MEI_IAMTHIF_READING;
598         dev->iamthif_flow_control_pending = false;
599         dev->iamthif_msg_buf_index = 0;
600         dev->iamthif_msg_buf_size = 0;
601         dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
602         dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
603         return 0;
604 }
605
606 /**
607  * mei_amthif_complete - complete amthif callback.
608  *
609  * @dev: the device structure.
610  * @cb_pos: callback block.
611  */
612 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
613 {
614         if (dev->iamthif_canceled != 1) {
615                 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
616                 dev->iamthif_stall_timer = 0;
617                 memcpy(cb->response_buffer.data,
618                                 dev->iamthif_msg_buf,
619                                 dev->iamthif_msg_buf_index);
620                 list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
621                 dev_dbg(&dev->pdev->dev, "amthif read completed\n");
622                 dev->iamthif_timer = jiffies;
623                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
624                                 dev->iamthif_timer);
625         } else {
626                 mei_amthif_run_next_cmd(dev);
627         }
628
629         dev_dbg(&dev->pdev->dev, "completing amthif call back.\n");
630         wake_up_interruptible(&dev->iamthif_cl.wait);
631 }
632
633 /**
634  * mei_clear_list - removes all callbacks associated with file
635  *              from mei_cb_list
636  *
637  * @dev: device structure.
638  * @file: file structure
639  * @mei_cb_list: callbacks list
640  *
641  * mei_clear_list is called to clear resources associated with file
642  * when application calls close function or Ctrl-C was pressed
643  *
644  * returns true if callback removed from the list, false otherwise
645  */
646 static bool mei_clear_list(struct mei_device *dev,
647                 const struct file *file, struct list_head *mei_cb_list)
648 {
649         struct mei_cl_cb *cb_pos = NULL;
650         struct mei_cl_cb *cb_next = NULL;
651         bool removed = false;
652
653         /* list all list member */
654         list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
655                 /* check if list member associated with a file */
656                 if (file == cb_pos->file_object) {
657                         /* remove member from the list */
658                         list_del(&cb_pos->list);
659                         /* check if cb equal to current iamthif cb */
660                         if (dev->iamthif_current_cb == cb_pos) {
661                                 dev->iamthif_current_cb = NULL;
662                                 /* send flow control to iamthif client */
663                                 mei_hbm_cl_flow_control_req(dev,
664                                                         &dev->iamthif_cl);
665                         }
666                         /* free all allocated buffers */
667                         mei_io_cb_free(cb_pos);
668                         cb_pos = NULL;
669                         removed = true;
670                 }
671         }
672         return removed;
673 }
674
675 /**
676  * mei_clear_lists - removes all callbacks associated with file
677  *
678  * @dev: device structure
679  * @file: file structure
680  *
681  * mei_clear_lists is called to clear resources associated with file
682  * when application calls close function or Ctrl-C was pressed
683  *
684  * returns true if callback removed from the list, false otherwise
685  */
686 static bool mei_clear_lists(struct mei_device *dev, struct file *file)
687 {
688         bool removed = false;
689
690         /* remove callbacks associated with a file */
691         mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
692         if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
693                 removed = true;
694
695         mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
696
697         if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
698                 removed = true;
699
700         if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
701                 removed = true;
702
703         if (mei_clear_list(dev, file, &dev->write_list.list))
704                 removed = true;
705
706         /* check if iamthif_current_cb not NULL */
707         if (dev->iamthif_current_cb && !removed) {
708                 /* check file and iamthif current cb association */
709                 if (dev->iamthif_current_cb->file_object == file) {
710                         /* remove cb */
711                         mei_io_cb_free(dev->iamthif_current_cb);
712                         dev->iamthif_current_cb = NULL;
713                         removed = true;
714                 }
715         }
716         return removed;
717 }
718
719 /**
720 * mei_amthif_release - the release function
721 *
722 *  @dev: device structure
723 *  @file: pointer to file structure
724 *
725 *  returns 0 on success, <0 on error
726 */
727 int mei_amthif_release(struct mei_device *dev, struct file *file)
728 {
729         if (dev->iamthif_open_count > 0)
730                 dev->iamthif_open_count--;
731
732         if (dev->iamthif_file_object == file &&
733             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
734
735                 dev_dbg(&dev->pdev->dev, "amthif canceled iamthif state %d\n",
736                     dev->iamthif_state);
737                 dev->iamthif_canceled = true;
738                 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
739                         dev_dbg(&dev->pdev->dev, "run next amthif iamthif cb\n");
740                         mei_amthif_run_next_cmd(dev);
741                 }
742         }
743
744         if (mei_clear_lists(dev, file))
745                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
746
747         return 0;
748 }