2052609b167a9e37ff716c1ecbaff93e50c77d1b
[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         cl->state = MEI_FILE_CONNECTING;
115
116         ret = mei_cl_connect(cl, NULL);
117
118         dev->iamthif_state = MEI_IAMTHIF_IDLE;
119
120         return ret;
121 }
122
123 /**
124  * mei_amthif_find_read_list_entry - finds a amthilist entry for current file
125  *
126  * @dev: the device structure
127  * @file: pointer to file object
128  *
129  * returns   returned a list entry on success, NULL on failure.
130  */
131 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
132                                                 struct file *file)
133 {
134         struct mei_cl_cb *cb;
135
136         list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) {
137                 if (cb->cl && cb->cl == &dev->iamthif_cl &&
138                         cb->file_object == file)
139                         return cb;
140         }
141         return NULL;
142 }
143
144
145 /**
146  * mei_amthif_read - read data from AMTHIF client
147  *
148  * @dev: the device structure
149  * @if_num:  minor number
150  * @file: pointer to file object
151  * @*ubuf: pointer to user data in user space
152  * @length: data length to read
153  * @offset: data read offset
154  *
155  * Locking: called under "dev->device_lock" lock
156  *
157  * returns
158  *  returned data length on success,
159  *  zero if no data to read,
160  *  negative on failure.
161  */
162 int mei_amthif_read(struct mei_device *dev, struct file *file,
163                char __user *ubuf, size_t length, loff_t *offset)
164 {
165         int rets;
166         int wait_ret;
167         struct mei_cl_cb *cb = NULL;
168         struct mei_cl *cl = file->private_data;
169         unsigned long timeout;
170         int i;
171
172         /* Only possible if we are in timeout */
173         if (!cl || cl != &dev->iamthif_cl) {
174                 dev_dbg(&dev->pdev->dev, "bad file ext.\n");
175                 return -ETIME;
176         }
177
178         i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
179         if (i < 0) {
180                 dev_dbg(&dev->pdev->dev, "amthif client not found.\n");
181                 return -ENOTTY;
182         }
183         dev_dbg(&dev->pdev->dev, "checking amthif data\n");
184         cb = mei_amthif_find_read_list_entry(dev, file);
185
186         /* Check for if we can block or not*/
187         if (cb == NULL && file->f_flags & O_NONBLOCK)
188                 return -EAGAIN;
189
190
191         dev_dbg(&dev->pdev->dev, "waiting for amthif data\n");
192         while (cb == NULL) {
193                 /* unlock the Mutex */
194                 mutex_unlock(&dev->device_lock);
195
196                 wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
197                         (cb = mei_amthif_find_read_list_entry(dev, file)));
198
199                 /* Locking again the Mutex */
200                 mutex_lock(&dev->device_lock);
201
202                 if (wait_ret)
203                         return -ERESTARTSYS;
204
205                 dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
206         }
207
208
209         dev_dbg(&dev->pdev->dev, "Got amthif data\n");
210         dev->iamthif_timer = 0;
211
212         if (cb) {
213                 timeout = cb->read_time +
214                         mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
215                 dev_dbg(&dev->pdev->dev, "amthif timeout = %lud\n",
216                                 timeout);
217
218                 if  (time_after(jiffies, timeout)) {
219                         dev_dbg(&dev->pdev->dev, "amthif Time out\n");
220                         /* 15 sec for the message has expired */
221                         list_del(&cb->list);
222                         rets = -ETIME;
223                         goto free;
224                 }
225         }
226         /* if the whole message will fit remove it from the list */
227         if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
228                 list_del(&cb->list);
229         else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
230                 /* end of the message has been reached */
231                 list_del(&cb->list);
232                 rets = 0;
233                 goto free;
234         }
235                 /* else means that not full buffer will be read and do not
236                  * remove message from deletion list
237                  */
238
239         dev_dbg(&dev->pdev->dev, "amthif cb->response_buffer size - %d\n",
240             cb->response_buffer.size);
241         dev_dbg(&dev->pdev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx);
242
243         /* length is being truncated to PAGE_SIZE, however,
244          * the buf_idx may point beyond */
245         length = min_t(size_t, length, (cb->buf_idx - *offset));
246
247         if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
248                 dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
249                 rets = -EFAULT;
250         }
251         else {
252                 rets = length;
253                 if ((*offset + length) < cb->buf_idx) {
254                         *offset += length;
255                         goto out;
256                 }
257         }
258 free:
259         dev_dbg(&dev->pdev->dev, "free amthif cb memory.\n");
260         *offset = 0;
261         mei_io_cb_free(cb);
262 out:
263         return rets;
264 }
265
266 /**
267  * mei_amthif_send_cmd - send amthif command to the ME
268  *
269  * @dev: the device structure
270  * @cb: mei call back struct
271  *
272  * returns 0 on success, <0 on failure.
273  *
274  */
275 static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
276 {
277         struct mei_msg_hdr mei_hdr;
278         int ret;
279
280         if (!dev || !cb)
281                 return -ENODEV;
282
283         dev_dbg(&dev->pdev->dev, "write data to amthif client.\n");
284
285         dev->iamthif_state = MEI_IAMTHIF_WRITING;
286         dev->iamthif_current_cb = cb;
287         dev->iamthif_file_object = cb->file_object;
288         dev->iamthif_canceled = false;
289         dev->iamthif_ioctl = true;
290         dev->iamthif_msg_buf_size = cb->request_buffer.size;
291         memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
292                cb->request_buffer.size);
293
294         ret = mei_cl_flow_ctrl_creds(&dev->iamthif_cl);
295         if (ret < 0)
296                 return ret;
297
298         if (ret && mei_hbuf_acquire(dev)) {
299                 ret = 0;
300                 if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
301                         mei_hdr.length = mei_hbuf_max_len(dev);
302                         mei_hdr.msg_complete = 0;
303                 } else {
304                         mei_hdr.length = cb->request_buffer.size;
305                         mei_hdr.msg_complete = 1;
306                 }
307
308                 mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
309                 mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
310                 mei_hdr.reserved = 0;
311                 mei_hdr.internal = 0;
312                 dev->iamthif_msg_buf_index += mei_hdr.length;
313                 ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
314                 if (ret)
315                         return ret;
316
317                 if (mei_hdr.msg_complete) {
318                         if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
319                                 return -EIO;
320                         dev->iamthif_flow_control_pending = true;
321                         dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
322                         dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
323                         dev->iamthif_current_cb = cb;
324                         dev->iamthif_file_object = cb->file_object;
325                         list_add_tail(&cb->list, &dev->write_waiting_list.list);
326                 } else {
327                         dev_dbg(&dev->pdev->dev, "message does not complete, so add amthif cb to write list.\n");
328                         list_add_tail(&cb->list, &dev->write_list.list);
329                 }
330         } else {
331                 list_add_tail(&cb->list, &dev->write_list.list);
332         }
333         return 0;
334 }
335
336 /**
337  * mei_amthif_write - write amthif data to amthif client
338  *
339  * @dev: the device structure
340  * @cb: mei call back struct
341  *
342  * returns 0 on success, <0 on failure.
343  *
344  */
345 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
346 {
347         int ret;
348
349         if (!dev || !cb)
350                 return -ENODEV;
351
352         ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
353         if (ret)
354                 return ret;
355
356         cb->fop_type = MEI_FOP_WRITE;
357
358         if (!list_empty(&dev->amthif_cmd_list.list) ||
359             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
360                 dev_dbg(&dev->pdev->dev,
361                         "amthif state = %d\n", dev->iamthif_state);
362                 dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
363                 list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
364                 return 0;
365         }
366         return mei_amthif_send_cmd(dev, cb);
367 }
368 /**
369  * mei_amthif_run_next_cmd
370  *
371  * @dev: the device structure
372  *
373  * returns 0 on success, <0 on failure.
374  */
375 void mei_amthif_run_next_cmd(struct mei_device *dev)
376 {
377         struct mei_cl_cb *pos = NULL;
378         struct mei_cl_cb *next = NULL;
379         int status;
380
381         if (!dev)
382                 return;
383
384         dev->iamthif_msg_buf_size = 0;
385         dev->iamthif_msg_buf_index = 0;
386         dev->iamthif_canceled = false;
387         dev->iamthif_ioctl = true;
388         dev->iamthif_state = MEI_IAMTHIF_IDLE;
389         dev->iamthif_timer = 0;
390         dev->iamthif_file_object = NULL;
391
392         dev_dbg(&dev->pdev->dev, "complete amthif cmd_list cb.\n");
393
394         list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
395                 list_del(&pos->list);
396
397                 if (pos->cl && pos->cl == &dev->iamthif_cl) {
398                         status = mei_amthif_send_cmd(dev, pos);
399                         if (status) {
400                                 dev_dbg(&dev->pdev->dev,
401                                         "amthif write failed status = %d\n",
402                                                 status);
403                                 return;
404                         }
405                         break;
406                 }
407         }
408 }
409
410
411 unsigned int mei_amthif_poll(struct mei_device *dev,
412                 struct file *file, poll_table *wait)
413 {
414         unsigned int mask = 0;
415
416         poll_wait(file, &dev->iamthif_cl.wait, wait);
417
418         mutex_lock(&dev->device_lock);
419         if (!mei_cl_is_connected(&dev->iamthif_cl)) {
420
421                 mask = POLLERR;
422
423         } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
424                    dev->iamthif_file_object == file) {
425
426                 mask |= (POLLIN | POLLRDNORM);
427                 dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
428                 mei_amthif_run_next_cmd(dev);
429         }
430         mutex_unlock(&dev->device_lock);
431
432         return mask;
433 }
434
435
436
437 /**
438  * mei_amthif_irq_write - write iamthif command in irq thread context.
439  *
440  * @dev: the device structure.
441  * @cb_pos: callback block.
442  * @cl: private data of the file object.
443  * @cmpl_list: complete list.
444  *
445  * returns 0, OK; otherwise, error.
446  */
447 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
448                          struct mei_cl_cb *cmpl_list)
449 {
450         struct mei_device *dev = cl->dev;
451         struct mei_msg_hdr mei_hdr;
452         size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
453         u32 msg_slots = mei_data2slots(len);
454         int slots;
455         int rets;
456
457         rets = mei_cl_flow_ctrl_creds(cl);
458         if (rets < 0)
459                 return rets;
460
461         if (rets == 0) {
462                 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
463                 return 0;
464         }
465
466         mei_hdr.host_addr = cl->host_client_id;
467         mei_hdr.me_addr = cl->me_client_id;
468         mei_hdr.reserved = 0;
469         mei_hdr.internal = 0;
470
471         slots = mei_hbuf_empty_slots(dev);
472
473         if (slots >= msg_slots) {
474                 mei_hdr.length = len;
475                 mei_hdr.msg_complete = 1;
476         /* Split the message only if we can write the whole host buffer */
477         } else if (slots == dev->hbuf_depth) {
478                 msg_slots = slots;
479                 len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
480                 mei_hdr.length = len;
481                 mei_hdr.msg_complete = 0;
482         } else {
483                 /* wait for next time the host buffer is empty */
484                 return 0;
485         }
486
487         dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
488
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 }