]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/misc/mei/amthif.c
Merge branch 'overlayfs-af_unix-fix' into overlayfs-linus
[karo-tx-linux.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/ioctl.h>
23 #include <linux/cdev.h>
24 #include <linux/list.h>
25 #include <linux/delay.h>
26 #include <linux/sched.h>
27 #include <linux/uuid.h>
28 #include <linux/jiffies.h>
29 #include <linux/uaccess.h>
30 #include <linux/slab.h>
31
32 #include <linux/mei.h>
33
34 #include "mei_dev.h"
35 #include "hbm.h"
36 #include "client.h"
37
38 const uuid_le mei_amthif_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
39                                          0xac, 0xa8, 0x46, 0xe0,
40                                          0xff, 0x65, 0x81, 0x4c);
41
42 /**
43  * mei_amthif_reset_params - initializes mei device iamthif
44  *
45  * @dev: the device structure
46  */
47 void mei_amthif_reset_params(struct mei_device *dev)
48 {
49         /* reset iamthif parameters. */
50         dev->iamthif_current_cb = NULL;
51         dev->iamthif_canceled = false;
52         dev->iamthif_state = MEI_IAMTHIF_IDLE;
53         dev->iamthif_stall_timer = 0;
54         dev->iamthif_open_count = 0;
55 }
56
57 /**
58  * mei_amthif_host_init - mei initialization amthif client.
59  *
60  * @dev: the device structure
61  * @me_cl: me client
62  *
63  * Return: 0 on success, <0 on failure.
64  */
65 int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
66 {
67         struct mei_cl *cl = &dev->iamthif_cl;
68         int ret;
69
70         if (mei_cl_is_connected(cl))
71                 return 0;
72
73         dev->iamthif_state = MEI_IAMTHIF_IDLE;
74
75         mei_cl_init(cl, dev);
76
77         ret = mei_cl_link(cl);
78         if (ret < 0) {
79                 dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
80                 return ret;
81         }
82
83         ret = mei_cl_connect(cl, me_cl, NULL);
84
85         return ret;
86 }
87
88 /**
89  * mei_amthif_read - read data from AMTHIF client
90  *
91  * @dev: the device structure
92  * @file: pointer to file object
93  * @ubuf: pointer to user data in user space
94  * @length: data length to read
95  * @offset: data read offset
96  *
97  * Locking: called under "dev->device_lock" lock
98  *
99  * Return:
100  *  returned data length on success,
101  *  zero if no data to read,
102  *  negative on failure.
103  */
104 int mei_amthif_read(struct mei_device *dev, struct file *file,
105                char __user *ubuf, size_t length, loff_t *offset)
106 {
107         struct mei_cl *cl = file->private_data;
108         struct mei_cl_cb *cb;
109         int rets;
110         int wait_ret;
111
112         dev_dbg(dev->dev, "checking amthif data\n");
113         cb = mei_cl_read_cb(cl, file);
114
115         /* Check for if we can block or not*/
116         if (cb == NULL && file->f_flags & O_NONBLOCK)
117                 return -EAGAIN;
118
119
120         dev_dbg(dev->dev, "waiting for amthif data\n");
121         while (cb == NULL) {
122                 /* unlock the Mutex */
123                 mutex_unlock(&dev->device_lock);
124
125                 wait_ret = wait_event_interruptible(cl->rx_wait,
126                                         !list_empty(&cl->rd_completed) ||
127                                         !mei_cl_is_connected(cl));
128
129                 /* Locking again the Mutex */
130                 mutex_lock(&dev->device_lock);
131
132                 if (wait_ret)
133                         return -ERESTARTSYS;
134
135                 if (!mei_cl_is_connected(cl)) {
136                         rets = -EBUSY;
137                         goto out;
138                 }
139
140                 cb = mei_cl_read_cb(cl, file);
141         }
142
143         if (cb->status) {
144                 rets = cb->status;
145                 dev_dbg(dev->dev, "read operation failed %d\n", rets);
146                 goto free;
147         }
148
149         dev_dbg(dev->dev, "Got amthif data\n");
150         /* if the whole message will fit remove it from the list */
151         if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
152                 list_del_init(&cb->list);
153         else if (cb->buf_idx <= *offset) {
154                 /* end of the message has been reached */
155                 list_del_init(&cb->list);
156                 rets = 0;
157                 goto free;
158         }
159                 /* else means that not full buffer will be read and do not
160                  * remove message from deletion list
161                  */
162
163         dev_dbg(dev->dev, "amthif cb->buf.size - %zu cb->buf_idx - %zu\n",
164                 cb->buf.size, cb->buf_idx);
165
166         /* length is being truncated to PAGE_SIZE, however,
167          * the buf_idx may point beyond */
168         length = min_t(size_t, length, (cb->buf_idx - *offset));
169
170         if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
171                 dev_dbg(dev->dev, "failed to copy data to userland\n");
172                 rets = -EFAULT;
173         } else {
174                 rets = length;
175                 if ((*offset + length) < cb->buf_idx) {
176                         *offset += length;
177                         goto out;
178                 }
179         }
180 free:
181         dev_dbg(dev->dev, "free amthif cb memory.\n");
182         *offset = 0;
183         mei_io_cb_free(cb);
184 out:
185         return rets;
186 }
187
188 /**
189  * mei_amthif_read_start - queue message for sending read credential
190  *
191  * @cl: host client
192  * @file: file pointer of message recipient
193  *
194  * Return: 0 on success, <0 on failure.
195  */
196 static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file)
197 {
198         struct mei_device *dev = cl->dev;
199         struct mei_cl_cb *cb;
200         int rets;
201
202         cb = mei_io_cb_init(cl, MEI_FOP_READ, file);
203         if (!cb) {
204                 rets = -ENOMEM;
205                 goto err;
206         }
207
208         rets = mei_io_cb_alloc_buf(cb, mei_cl_mtu(cl));
209         if (rets)
210                 goto err;
211
212         list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
213
214         dev->iamthif_state = MEI_IAMTHIF_READING;
215         dev->iamthif_fp = cb->fp;
216         dev->iamthif_current_cb = cb;
217
218         return 0;
219 err:
220         mei_io_cb_free(cb);
221         return rets;
222 }
223
224 /**
225  * mei_amthif_send_cmd - send amthif command to the ME
226  *
227  * @cl: the host client
228  * @cb: mei call back struct
229  *
230  * Return: 0 on success, <0 on failure.
231  */
232 static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb)
233 {
234         struct mei_device *dev;
235         int ret;
236
237         if (!cl->dev || !cb)
238                 return -ENODEV;
239
240         dev = cl->dev;
241
242         dev->iamthif_state = MEI_IAMTHIF_WRITING;
243         dev->iamthif_current_cb = cb;
244         dev->iamthif_fp = cb->fp;
245         dev->iamthif_canceled = false;
246
247         ret = mei_cl_write(cl, cb, false);
248         if (ret < 0)
249                 return ret;
250
251         if (cb->completed)
252                 cb->status = mei_amthif_read_start(cl, cb->fp);
253
254         return 0;
255 }
256
257 /**
258  * mei_amthif_run_next_cmd - send next amt command from queue
259  *
260  * @dev: the device structure
261  *
262  * Return: 0 on success, <0 on failure.
263  */
264 int mei_amthif_run_next_cmd(struct mei_device *dev)
265 {
266         struct mei_cl *cl = &dev->iamthif_cl;
267         struct mei_cl_cb *cb;
268
269         dev->iamthif_canceled = false;
270         dev->iamthif_state = MEI_IAMTHIF_IDLE;
271         dev->iamthif_fp = NULL;
272
273         dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
274
275         cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
276                                         typeof(*cb), list);
277         if (!cb)
278                 return 0;
279
280         list_del_init(&cb->list);
281         return mei_amthif_send_cmd(cl, cb);
282 }
283
284 /**
285  * mei_amthif_write - write amthif data to amthif client
286  *
287  * @cl: host client
288  * @cb: mei call back struct
289  *
290  * Return: 0 on success, <0 on failure.
291  */
292 int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
293 {
294
295         struct mei_device *dev = cl->dev;
296
297         list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
298
299         /*
300          * The previous request is still in processing, queue this one.
301          */
302         if (dev->iamthif_state > MEI_IAMTHIF_IDLE &&
303             dev->iamthif_state < MEI_IAMTHIF_READ_COMPLETE)
304                 return 0;
305
306         return mei_amthif_run_next_cmd(dev);
307 }
308
309 /**
310  * mei_amthif_poll - the amthif poll function
311  *
312  * @dev: the device structure
313  * @file: pointer to file structure
314  * @wait: pointer to poll_table structure
315  *
316  * Return: poll mask
317  *
318  * Locking: called under "dev->device_lock" lock
319  */
320
321 unsigned int mei_amthif_poll(struct mei_device *dev,
322                 struct file *file, poll_table *wait)
323 {
324         unsigned int mask = 0;
325
326         poll_wait(file, &dev->iamthif_cl.rx_wait, wait);
327
328         if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
329             dev->iamthif_fp == file) {
330
331                 mask |= POLLIN | POLLRDNORM;
332                 mei_amthif_run_next_cmd(dev);
333         }
334
335         return mask;
336 }
337
338
339
340 /**
341  * mei_amthif_irq_write - write iamthif command in irq thread context.
342  *
343  * @cl: private data of the file object.
344  * @cb: callback block.
345  * @cmpl_list: complete list.
346  *
347  * Return: 0, OK; otherwise, error.
348  */
349 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
350                          struct mei_cl_cb *cmpl_list)
351 {
352         int ret;
353
354         ret = mei_cl_irq_write(cl, cb, cmpl_list);
355         if (ret)
356                 return ret;
357
358         if (cb->completed)
359                 cb->status = mei_amthif_read_start(cl, cb->fp);
360
361         return 0;
362 }
363
364 /**
365  * mei_amthif_irq_read_msg - read routine after ISR to
366  *                      handle the read amthif message
367  *
368  * @cl: mei client
369  * @mei_hdr: header of amthif message
370  * @cmpl_list: completed callbacks list
371  *
372  * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
373  */
374 int mei_amthif_irq_read_msg(struct mei_cl *cl,
375                             struct mei_msg_hdr *mei_hdr,
376                             struct mei_cl_cb *cmpl_list)
377 {
378         struct mei_device *dev;
379         int ret;
380
381         dev = cl->dev;
382
383         if (dev->iamthif_state != MEI_IAMTHIF_READING) {
384                 mei_irq_discard_msg(dev, mei_hdr);
385                 return 0;
386         }
387
388         ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
389         if (ret)
390                 return ret;
391
392         if (!mei_hdr->msg_complete)
393                 return 0;
394
395         dev_dbg(dev->dev, "completed amthif read.\n ");
396         dev->iamthif_current_cb = NULL;
397         dev->iamthif_stall_timer = 0;
398
399         return 0;
400 }
401
402 /**
403  * mei_amthif_complete - complete amthif callback.
404  *
405  * @cl: host client
406  * @cb: callback block.
407  */
408 void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
409 {
410         struct mei_device *dev = cl->dev;
411
412         if (cb->fop_type == MEI_FOP_WRITE) {
413                 if (!cb->status) {
414                         dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
415                         mei_io_cb_free(cb);
416                         return;
417                 }
418                 /*
419                  * in case of error enqueue the write cb to complete read list
420                  * so it can be propagated to the reader
421                  */
422                 list_add_tail(&cb->list, &cl->rd_completed);
423                 wake_up_interruptible(&cl->rx_wait);
424                 return;
425         }
426
427         if (!dev->iamthif_canceled) {
428                 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
429                 dev->iamthif_stall_timer = 0;
430                 list_add_tail(&cb->list, &cl->rd_completed);
431                 dev_dbg(dev->dev, "amthif read completed\n");
432         } else {
433                 mei_amthif_run_next_cmd(dev);
434         }
435
436         dev_dbg(dev->dev, "completing amthif call back.\n");
437         wake_up_interruptible(&cl->rx_wait);
438 }
439
440 /**
441  * mei_clear_list - removes all callbacks associated with file
442  *              from mei_cb_list
443  *
444  * @dev: device structure.
445  * @file: file structure
446  * @mei_cb_list: callbacks list
447  *
448  * mei_clear_list is called to clear resources associated with file
449  * when application calls close function or Ctrl-C was pressed
450  *
451  * Return: true if callback removed from the list, false otherwise
452  */
453 static bool mei_clear_list(struct mei_device *dev,
454                 const struct file *file, struct list_head *mei_cb_list)
455 {
456         struct mei_cl *cl = &dev->iamthif_cl;
457         struct mei_cl_cb *cb, *next;
458         bool removed = false;
459
460         /* list all list member */
461         list_for_each_entry_safe(cb, next, mei_cb_list, list) {
462                 /* check if list member associated with a file */
463                 if (file == cb->fp) {
464                         /* check if cb equal to current iamthif cb */
465                         if (dev->iamthif_current_cb == cb) {
466                                 dev->iamthif_current_cb = NULL;
467                                 /* send flow control to iamthif client */
468                                 mei_hbm_cl_flow_control_req(dev, cl);
469                         }
470                         /* free all allocated buffers */
471                         mei_io_cb_free(cb);
472                         removed = true;
473                 }
474         }
475         return removed;
476 }
477
478 /**
479  * mei_clear_lists - removes all callbacks associated with file
480  *
481  * @dev: device structure
482  * @file: file structure
483  *
484  * mei_clear_lists is called to clear resources associated with file
485  * when application calls close function or Ctrl-C was pressed
486  *
487  * Return: true if callback removed from the list, false otherwise
488  */
489 static bool mei_clear_lists(struct mei_device *dev, const struct file *file)
490 {
491         bool removed = false;
492         struct mei_cl *cl = &dev->iamthif_cl;
493
494         /* remove callbacks associated with a file */
495         mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
496         if (mei_clear_list(dev, file, &cl->rd_completed))
497                 removed = true;
498
499         mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
500
501         if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
502                 removed = true;
503
504         if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
505                 removed = true;
506
507         if (mei_clear_list(dev, file, &dev->write_list.list))
508                 removed = true;
509
510         /* check if iamthif_current_cb not NULL */
511         if (dev->iamthif_current_cb && !removed) {
512                 /* check file and iamthif current cb association */
513                 if (dev->iamthif_current_cb->fp == file) {
514                         /* remove cb */
515                         mei_io_cb_free(dev->iamthif_current_cb);
516                         dev->iamthif_current_cb = NULL;
517                         removed = true;
518                 }
519         }
520         return removed;
521 }
522
523 /**
524 * mei_amthif_release - the release function
525 *
526 *  @dev: device structure
527 *  @file: pointer to file structure
528 *
529 *  Return: 0 on success, <0 on error
530 */
531 int mei_amthif_release(struct mei_device *dev, struct file *file)
532 {
533         if (dev->iamthif_open_count > 0)
534                 dev->iamthif_open_count--;
535
536         if (dev->iamthif_fp == file &&
537             dev->iamthif_state != MEI_IAMTHIF_IDLE) {
538
539                 dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
540                     dev->iamthif_state);
541                 dev->iamthif_canceled = true;
542                 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
543                         dev_dbg(dev->dev, "run next amthif iamthif cb\n");
544                         mei_amthif_run_next_cmd(dev);
545                 }
546         }
547
548         if (mei_clear_lists(dev, file))
549                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
550
551         return 0;
552 }