hwrng: core - Don't use a stack buffer in add_early_randomness()
[linux/fpc-iii.git] / drivers / misc / mei / amthif.c
blob7ae89b4a21d5de5b884d943b0a906b2571e3e7e9
1 /*
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
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.
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.
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>
32 #include <linux/mei.h>
34 #include "mei_dev.h"
35 #include "hbm.h"
36 #include "client.h"
38 const uuid_le mei_amthif_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
39 0xac, 0xa8, 0x46, 0xe0,
40 0xff, 0x65, 0x81, 0x4c);
42 /**
43 * mei_amthif_reset_params - initializes mei device iamthif
45 * @dev: the device structure
47 void mei_amthif_reset_params(struct mei_device *dev)
49 /* reset iamthif parameters. */
50 dev->iamthif_canceled = false;
51 dev->iamthif_state = MEI_IAMTHIF_IDLE;
52 dev->iamthif_stall_timer = 0;
53 dev->iamthif_open_count = 0;
56 /**
57 * mei_amthif_host_init - mei initialization amthif client.
59 * @dev: the device structure
60 * @me_cl: me client
62 * Return: 0 on success, <0 on failure.
64 int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
66 struct mei_cl *cl = &dev->iamthif_cl;
67 int ret;
69 mutex_lock(&dev->device_lock);
71 if (mei_cl_is_connected(cl)) {
72 ret = 0;
73 goto out;
76 dev->iamthif_state = MEI_IAMTHIF_IDLE;
78 mei_cl_init(cl, dev);
80 ret = mei_cl_link(cl);
81 if (ret < 0) {
82 dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
83 goto out;
86 ret = mei_cl_connect(cl, me_cl, NULL);
88 out:
89 mutex_unlock(&dev->device_lock);
90 return ret;
93 /**
94 * mei_amthif_read_start - queue message for sending read credential
96 * @cl: host client
97 * @fp: file pointer of message recipient
99 * Return: 0 on success, <0 on failure.
101 static int mei_amthif_read_start(struct mei_cl *cl, const struct file *fp)
103 struct mei_device *dev = cl->dev;
104 struct mei_cl_cb *cb;
106 cb = mei_cl_enqueue_ctrl_wr_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, fp);
107 if (!cb)
108 return -ENOMEM;
110 cl->rx_flow_ctrl_creds++;
112 dev->iamthif_state = MEI_IAMTHIF_READING;
113 cl->fp = cb->fp;
115 return 0;
119 * mei_amthif_run_next_cmd - send next amt command from queue
121 * @dev: the device structure
123 * Return: 0 on success, <0 on failure.
125 int mei_amthif_run_next_cmd(struct mei_device *dev)
127 struct mei_cl *cl = &dev->iamthif_cl;
128 struct mei_cl_cb *cb;
129 int ret;
131 dev->iamthif_canceled = false;
133 dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
135 cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
136 typeof(*cb), list);
137 if (!cb) {
138 dev->iamthif_state = MEI_IAMTHIF_IDLE;
139 cl->fp = NULL;
140 return 0;
143 list_del_init(&cb->list);
144 dev->iamthif_state = MEI_IAMTHIF_WRITING;
145 cl->fp = cb->fp;
147 ret = mei_cl_write(cl, cb, false);
148 if (ret < 0)
149 return ret;
151 if (cb->completed)
152 cb->status = mei_amthif_read_start(cl, cb->fp);
154 return 0;
158 * mei_amthif_write - write amthif data to amthif client
160 * @cl: host client
161 * @cb: mei call back struct
163 * Return: 0 on success, <0 on failure.
165 int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
168 struct mei_device *dev = cl->dev;
170 list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
173 * The previous request is still in processing, queue this one.
175 if (dev->iamthif_state != MEI_IAMTHIF_IDLE)
176 return 0;
178 return mei_amthif_run_next_cmd(dev);
182 * mei_amthif_poll - the amthif poll function
184 * @file: pointer to file structure
185 * @wait: pointer to poll_table structure
187 * Return: poll mask
189 * Locking: called under "dev->device_lock" lock
191 unsigned int mei_amthif_poll(struct file *file, poll_table *wait)
193 struct mei_cl *cl = file->private_data;
194 struct mei_cl_cb *cb = mei_cl_read_cb(cl, file);
195 unsigned int mask = 0;
197 poll_wait(file, &cl->rx_wait, wait);
198 if (cb)
199 mask |= POLLIN | POLLRDNORM;
201 return mask;
205 * mei_amthif_irq_write - write iamthif command in irq thread context.
207 * @cl: private data of the file object.
208 * @cb: callback block.
209 * @cmpl_list: complete list.
211 * Return: 0, OK; otherwise, error.
213 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
214 struct mei_cl_cb *cmpl_list)
216 int ret;
218 ret = mei_cl_irq_write(cl, cb, cmpl_list);
219 if (ret)
220 return ret;
222 if (cb->completed)
223 cb->status = mei_amthif_read_start(cl, cb->fp);
225 return 0;
229 * mei_amthif_irq_read_msg - read routine after ISR to
230 * handle the read amthif message
232 * @cl: mei client
233 * @mei_hdr: header of amthif message
234 * @cmpl_list: completed callbacks list
236 * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
238 int mei_amthif_irq_read_msg(struct mei_cl *cl,
239 struct mei_msg_hdr *mei_hdr,
240 struct mei_cl_cb *cmpl_list)
242 struct mei_device *dev;
243 int ret;
245 dev = cl->dev;
247 if (dev->iamthif_state != MEI_IAMTHIF_READING) {
248 mei_irq_discard_msg(dev, mei_hdr);
249 return 0;
252 ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
253 if (ret)
254 return ret;
256 if (!mei_hdr->msg_complete)
257 return 0;
259 dev_dbg(dev->dev, "completed amthif read.\n ");
260 dev->iamthif_stall_timer = 0;
262 return 0;
266 * mei_amthif_complete - complete amthif callback.
268 * @cl: host client
269 * @cb: callback block.
271 void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
273 struct mei_device *dev = cl->dev;
275 dev_dbg(dev->dev, "completing amthif call back.\n");
276 switch (cb->fop_type) {
277 case MEI_FOP_WRITE:
278 if (!cb->status) {
279 dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
280 mei_schedule_stall_timer(dev);
281 mei_io_cb_free(cb);
282 return;
284 dev->iamthif_state = MEI_IAMTHIF_IDLE;
285 cl->fp = NULL;
286 if (!dev->iamthif_canceled) {
288 * in case of error enqueue the write cb to complete
289 * read list so it can be propagated to the reader
291 list_add_tail(&cb->list, &cl->rd_completed);
292 wake_up_interruptible(&cl->rx_wait);
293 } else {
294 mei_io_cb_free(cb);
296 break;
297 case MEI_FOP_READ:
298 if (!dev->iamthif_canceled) {
299 list_add_tail(&cb->list, &cl->rd_completed);
300 dev_dbg(dev->dev, "amthif read completed\n");
301 wake_up_interruptible(&cl->rx_wait);
302 } else {
303 mei_io_cb_free(cb);
306 dev->iamthif_stall_timer = 0;
307 mei_amthif_run_next_cmd(dev);
308 break;
309 default:
310 WARN_ON(1);
315 * mei_clear_list - removes all callbacks associated with file
316 * from mei_cb_list
318 * @file: file structure
319 * @mei_cb_list: callbacks list
321 * mei_clear_list is called to clear resources associated with file
322 * when application calls close function or Ctrl-C was pressed
324 static void mei_clear_list(const struct file *file,
325 struct list_head *mei_cb_list)
327 struct mei_cl_cb *cb, *next;
329 list_for_each_entry_safe(cb, next, mei_cb_list, list)
330 if (file == cb->fp)
331 mei_io_cb_free(cb);
335 * mei_amthif_release - the release function
337 * @dev: device structure
338 * @file: pointer to file structure
340 * Return: 0 on success, <0 on error
342 int mei_amthif_release(struct mei_device *dev, struct file *file)
344 struct mei_cl *cl = file->private_data;
346 if (dev->iamthif_open_count > 0)
347 dev->iamthif_open_count--;
349 if (cl->fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) {
351 dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
352 dev->iamthif_state);
353 dev->iamthif_canceled = true;
356 mei_clear_list(file, &dev->amthif_cmd_list.list);
357 mei_clear_list(file, &cl->rd_completed);
358 mei_clear_list(file, &dev->ctrl_rd_list.list);
360 return 0;