mei: don't of list_for_each_entry_safe when not deleting
[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 && dev->hbuf_is_ready) {
300                 ret = 0;
301                 dev->hbuf_is_ready = false;
302                 if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
303                         mei_hdr.length = mei_hbuf_max_len(dev);
304                         mei_hdr.msg_complete = 0;
305                 } else {
306                         mei_hdr.length = cb->request_buffer.size;
307                         mei_hdr.msg_complete = 1;
308                 }
309
310                 mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
311                 mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
312                 mei_hdr.reserved = 0;
313                 mei_hdr.internal = 0;
314                 dev->iamthif_msg_buf_index += mei_hdr.length;
315                 ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
316                 if (ret)
317                         return ret;
318
319                 if (mei_hdr.msg_complete) {
320                         if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
321                                 return -EIO;
322                         dev->iamthif_flow_control_pending = true;
323                         dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
324                         dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
325                         dev->iamthif_current_cb = cb;
326                         dev->iamthif_file_object = cb->file_object;
327                         list_add_tail(&cb->list, &dev->write_waiting_list.list);
328                 } else {
329                         dev_dbg(&dev->pdev->dev, "message does not complete, so add amthif cb to write list.\n");
330                         list_add_tail(&cb->list, &dev->write_list.list);
331                 }
332         } else {
333                 if (!dev->hbuf_is_ready)
334                         dev_dbg(&dev->pdev->dev, "host buffer is not empty");
335
336                 dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
337                 list_add_tail(&cb->list, &dev->write_list.list);
338         }
339         return 0;
340 }
341
342 /**
343  * mei_amthif_write - write amthif data to amthif client
344  *
345  * @dev: the device structure
346  * @cb: mei call back struct
347  *
348  * returns 0 on success, <0 on failure.
349  *
350  */
351 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
352 {
353         int ret;
354
355         if (!dev || !cb)
356                 return -ENODEV;
357
358         ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
359         if (ret)
360                 return ret;
361
362         cb->fop_type = MEI_FOP_WRITE;
363
364         if (!list_empty(&dev->amthif_cmd_list.list) ||
365             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
366                 dev_dbg(&dev->pdev->dev,
367                         "amthif state = %d\n", dev->iamthif_state);
368                 dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
369                 list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
370                 return 0;
371         }
372         return mei_amthif_send_cmd(dev, cb);
373 }
374 /**
375  * mei_amthif_run_next_cmd
376  *
377  * @dev: the device structure
378  *
379  * returns 0 on success, <0 on failure.
380  */
381 void mei_amthif_run_next_cmd(struct mei_device *dev)
382 {
383         struct mei_cl_cb *pos = NULL;
384         struct mei_cl_cb *next = NULL;
385         int status;
386
387         if (!dev)
388                 return;
389
390         dev->iamthif_msg_buf_size = 0;
391         dev->iamthif_msg_buf_index = 0;
392         dev->iamthif_canceled = false;
393         dev->iamthif_ioctl = true;
394         dev->iamthif_state = MEI_IAMTHIF_IDLE;
395         dev->iamthif_timer = 0;
396         dev->iamthif_file_object = NULL;
397
398         dev_dbg(&dev->pdev->dev, "complete amthif cmd_list cb.\n");
399
400         list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
401                 list_del(&pos->list);
402
403                 if (pos->cl && pos->cl == &dev->iamthif_cl) {
404                         status = mei_amthif_send_cmd(dev, pos);
405                         if (status) {
406                                 dev_dbg(&dev->pdev->dev,
407                                         "amthif write failed status = %d\n",
408                                                 status);
409                                 return;
410                         }
411                         break;
412                 }
413         }
414 }
415
416
417 unsigned int mei_amthif_poll(struct mei_device *dev,
418                 struct file *file, poll_table *wait)
419 {
420         unsigned int mask = 0;
421
422         poll_wait(file, &dev->iamthif_cl.wait, wait);
423
424         mutex_lock(&dev->device_lock);
425         if (!mei_cl_is_connected(&dev->iamthif_cl)) {
426
427                 mask = POLLERR;
428
429         } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
430                    dev->iamthif_file_object == file) {
431
432                 mask |= (POLLIN | POLLRDNORM);
433                 dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
434                 mei_amthif_run_next_cmd(dev);
435         }
436         mutex_unlock(&dev->device_lock);
437
438         return mask;
439 }
440
441
442
443 /**
444  * mei_amthif_irq_write_completed - processes completed iamthif operation.
445  *
446  * @dev: the device structure.
447  * @slots: free slots.
448  * @cb_pos: callback block.
449  * @cl: private data of the file object.
450  * @cmpl_list: complete list.
451  *
452  * returns 0, OK; otherwise, error.
453  */
454 int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
455                                   s32 *slots, struct mei_cl_cb *cmpl_list)
456 {
457         struct mei_device *dev = cl->dev;
458         struct mei_msg_hdr mei_hdr;
459         size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
460         u32 msg_slots = mei_data2slots(len);
461         int rets;
462
463         rets = mei_cl_flow_ctrl_creds(cl);
464         if (rets < 0)
465                 return rets;
466
467         if (rets == 0) {
468                 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
469                 return 0;
470         }
471
472         mei_hdr.host_addr = cl->host_client_id;
473         mei_hdr.me_addr = cl->me_client_id;
474         mei_hdr.reserved = 0;
475         mei_hdr.internal = 0;
476
477         if (*slots >= msg_slots) {
478                 mei_hdr.length = len;
479                 mei_hdr.msg_complete = 1;
480         /* Split the message only if we can write the whole host buffer */
481         } else if (*slots == dev->hbuf_depth) {
482                 msg_slots = *slots;
483                 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
484                 mei_hdr.length = len;
485                 mei_hdr.msg_complete = 0;
486         } else {
487                 /* wait for next time the host buffer is empty */
488                 return 0;
489         }
490
491         dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
492
493         *slots -=  msg_slots;
494         rets = mei_write_message(dev, &mei_hdr,
495                         dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
496         if (rets) {
497                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
498                 cl->status = rets;
499                 list_del(&cb->list);
500                 return rets;
501         }
502
503         if (mei_cl_flow_ctrl_reduce(cl))
504                 return -EIO;
505
506         dev->iamthif_msg_buf_index += mei_hdr.length;
507         cl->status = 0;
508
509         if (mei_hdr.msg_complete) {
510                 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
511                 dev->iamthif_flow_control_pending = true;
512
513                 /* save iamthif cb sent to amthif client */
514                 cb->buf_idx = dev->iamthif_msg_buf_index;
515                 dev->iamthif_current_cb = cb;
516
517                 list_move_tail(&cb->list, &dev->write_waiting_list.list);
518         }
519
520
521         return 0;
522 }
523
524 /**
525  * mei_amthif_irq_read_message - read routine after ISR to
526  *                      handle the read amthif message
527  *
528  * @dev: the device structure
529  * @mei_hdr: header of amthif message
530  * @complete_list: An instance of our list structure
531  *
532  * returns 0 on success, <0 on failure.
533  */
534 int mei_amthif_irq_read_msg(struct mei_device *dev,
535                             struct mei_msg_hdr *mei_hdr,
536                             struct mei_cl_cb *complete_list)
537 {
538         struct mei_cl_cb *cb;
539         unsigned char *buffer;
540
541         BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
542         BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
543
544         buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
545         BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
546
547         mei_read_slots(dev, buffer, mei_hdr->length);
548
549         dev->iamthif_msg_buf_index += mei_hdr->length;
550
551         if (!mei_hdr->msg_complete)
552                 return 0;
553
554         dev_dbg(&dev->pdev->dev, "amthif_message_buffer_index =%d\n",
555                         mei_hdr->length);
556
557         dev_dbg(&dev->pdev->dev, "completed amthif read.\n ");
558         if (!dev->iamthif_current_cb)
559                 return -ENODEV;
560
561         cb = dev->iamthif_current_cb;
562         dev->iamthif_current_cb = NULL;
563
564         if (!cb->cl)
565                 return -ENODEV;
566
567         dev->iamthif_stall_timer = 0;
568         cb->buf_idx = dev->iamthif_msg_buf_index;
569         cb->read_time = jiffies;
570         if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
571                 /* found the iamthif cb */
572                 dev_dbg(&dev->pdev->dev, "complete the amthif read cb.\n ");
573                 dev_dbg(&dev->pdev->dev, "add the amthif read cb to complete.\n ");
574                 list_add_tail(&cb->list, &complete_list->list);
575         }
576         return 0;
577 }
578
579 /**
580  * mei_amthif_irq_read - prepares to read amthif data.
581  *
582  * @dev: the device structure.
583  * @slots: free slots.
584  *
585  * returns 0, OK; otherwise, error.
586  */
587 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
588 {
589         u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
590
591         if (*slots < msg_slots)
592                 return -EMSGSIZE;
593
594         *slots -= msg_slots;
595
596         if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
597                 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
598                 return -EIO;
599         }
600
601         dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
602         dev->iamthif_state = MEI_IAMTHIF_READING;
603         dev->iamthif_flow_control_pending = false;
604         dev->iamthif_msg_buf_index = 0;
605         dev->iamthif_msg_buf_size = 0;
606         dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
607         dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
608         return 0;
609 }
610
611 /**
612  * mei_amthif_complete - complete amthif callback.
613  *
614  * @dev: the device structure.
615  * @cb_pos: callback block.
616  */
617 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
618 {
619         if (dev->iamthif_canceled != 1) {
620                 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
621                 dev->iamthif_stall_timer = 0;
622                 memcpy(cb->response_buffer.data,
623                                 dev->iamthif_msg_buf,
624                                 dev->iamthif_msg_buf_index);
625                 list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
626                 dev_dbg(&dev->pdev->dev, "amthif read completed\n");
627                 dev->iamthif_timer = jiffies;
628                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
629                                 dev->iamthif_timer);
630         } else {
631                 mei_amthif_run_next_cmd(dev);
632         }
633
634         dev_dbg(&dev->pdev->dev, "completing amthif call back.\n");
635         wake_up_interruptible(&dev->iamthif_cl.wait);
636 }
637
638 /**
639  * mei_clear_list - removes all callbacks associated with file
640  *              from mei_cb_list
641  *
642  * @dev: device structure.
643  * @file: file structure
644  * @mei_cb_list: callbacks list
645  *
646  * mei_clear_list is called to clear resources associated with file
647  * when application calls close function or Ctrl-C was pressed
648  *
649  * returns true if callback removed from the list, false otherwise
650  */
651 static bool mei_clear_list(struct mei_device *dev,
652                 const struct file *file, struct list_head *mei_cb_list)
653 {
654         struct mei_cl_cb *cb_pos = NULL;
655         struct mei_cl_cb *cb_next = NULL;
656         bool removed = false;
657
658         /* list all list member */
659         list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
660                 /* check if list member associated with a file */
661                 if (file == cb_pos->file_object) {
662                         /* remove member from the list */
663                         list_del(&cb_pos->list);
664                         /* check if cb equal to current iamthif cb */
665                         if (dev->iamthif_current_cb == cb_pos) {
666                                 dev->iamthif_current_cb = NULL;
667                                 /* send flow control to iamthif client */
668                                 mei_hbm_cl_flow_control_req(dev,
669                                                         &dev->iamthif_cl);
670                         }
671                         /* free all allocated buffers */
672                         mei_io_cb_free(cb_pos);
673                         cb_pos = NULL;
674                         removed = true;
675                 }
676         }
677         return removed;
678 }
679
680 /**
681  * mei_clear_lists - removes all callbacks associated with file
682  *
683  * @dev: device structure
684  * @file: file structure
685  *
686  * mei_clear_lists is called to clear resources associated with file
687  * when application calls close function or Ctrl-C was pressed
688  *
689  * returns true if callback removed from the list, false otherwise
690  */
691 static bool mei_clear_lists(struct mei_device *dev, struct file *file)
692 {
693         bool removed = false;
694
695         /* remove callbacks associated with a file */
696         mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
697         if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
698                 removed = true;
699
700         mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
701
702         if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
703                 removed = true;
704
705         if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
706                 removed = true;
707
708         if (mei_clear_list(dev, file, &dev->write_list.list))
709                 removed = true;
710
711         /* check if iamthif_current_cb not NULL */
712         if (dev->iamthif_current_cb && !removed) {
713                 /* check file and iamthif current cb association */
714                 if (dev->iamthif_current_cb->file_object == file) {
715                         /* remove cb */
716                         mei_io_cb_free(dev->iamthif_current_cb);
717                         dev->iamthif_current_cb = NULL;
718                         removed = true;
719                 }
720         }
721         return removed;
722 }
723
724 /**
725 * mei_amthif_release - the release function
726 *
727 *  @dev: device structure
728 *  @file: pointer to file structure
729 *
730 *  returns 0 on success, <0 on error
731 */
732 int mei_amthif_release(struct mei_device *dev, struct file *file)
733 {
734         if (dev->iamthif_open_count > 0)
735                 dev->iamthif_open_count--;
736
737         if (dev->iamthif_file_object == file &&
738             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
739
740                 dev_dbg(&dev->pdev->dev, "amthif canceled iamthif state %d\n",
741                     dev->iamthif_state);
742                 dev->iamthif_canceled = true;
743                 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
744                         dev_dbg(&dev->pdev->dev, "run next amthif iamthif cb\n");
745                         mei_amthif_run_next_cmd(dev);
746                 }
747         }
748
749         if (mei_clear_lists(dev, file))
750                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
751
752         return 0;
753 }