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
17 #include <linux/kernel.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>
38 const uuid_le mei_amthif_guid
= UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
39 0xac, 0xa8, 0x46, 0xe0,
40 0xff, 0x65, 0x81, 0x4c);
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;
57 * mei_amthif_host_init - mei initialization amthif client.
59 * @dev: the device structure
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
;
69 mutex_lock(&dev
->device_lock
);
71 if (mei_cl_is_connected(cl
)) {
76 dev
->iamthif_state
= MEI_IAMTHIF_IDLE
;
80 ret
= mei_cl_link(cl
);
82 dev_err(dev
->dev
, "amthif: failed cl_link %d\n", ret
);
86 ret
= mei_cl_connect(cl
, me_cl
, NULL
);
89 mutex_unlock(&dev
->device_lock
);
94 * mei_amthif_read_start - queue message for sending read credential
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
);
110 cl
->rx_flow_ctrl_creds
++;
112 dev
->iamthif_state
= MEI_IAMTHIF_READING
;
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
;
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
,
138 dev
->iamthif_state
= MEI_IAMTHIF_IDLE
;
143 list_del_init(&cb
->list
);
144 dev
->iamthif_state
= MEI_IAMTHIF_WRITING
;
147 ret
= mei_cl_write(cl
, cb
, false);
152 cb
->status
= mei_amthif_read_start(cl
, cb
->fp
);
158 * mei_amthif_write - write amthif data to amthif 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
)
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
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
);
199 mask
|= POLLIN
| POLLRDNORM
;
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
)
218 ret
= mei_cl_irq_write(cl
, cb
, cmpl_list
);
223 cb
->status
= mei_amthif_read_start(cl
, cb
->fp
);
229 * mei_amthif_irq_read_msg - read routine after ISR to
230 * handle the read amthif message
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
;
247 if (dev
->iamthif_state
!= MEI_IAMTHIF_READING
) {
248 mei_irq_discard_msg(dev
, mei_hdr
);
252 ret
= mei_cl_irq_read_msg(cl
, mei_hdr
, cmpl_list
);
256 if (!mei_hdr
->msg_complete
)
259 dev_dbg(dev
->dev
, "completed amthif read.\n ");
260 dev
->iamthif_stall_timer
= 0;
266 * mei_amthif_complete - complete amthif callback.
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
) {
279 dev
->iamthif_stall_timer
= MEI_IAMTHIF_STALL_TIMER
;
280 mei_schedule_stall_timer(dev
);
284 dev
->iamthif_state
= MEI_IAMTHIF_IDLE
;
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
);
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
);
306 dev
->iamthif_stall_timer
= 0;
307 mei_amthif_run_next_cmd(dev
);
315 * mei_clear_list - removes all callbacks associated with file
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
)
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",
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
);