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