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/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/delay.h>
22 #include <linux/mei.h>
26 #include "interface.h"
28 const char *mei_dev_state_str(int state
)
30 #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
32 MEI_DEV_STATE(INITIALIZING
);
33 MEI_DEV_STATE(INIT_CLIENTS
);
34 MEI_DEV_STATE(ENABLED
);
35 MEI_DEV_STATE(RESETING
);
36 MEI_DEV_STATE(DISABLED
);
37 MEI_DEV_STATE(RECOVERING_FROM_RESET
);
38 MEI_DEV_STATE(POWER_DOWN
);
39 MEI_DEV_STATE(POWER_UP
);
49 * mei_io_list_flush - removes list entry belonging to cl.
51 * @list: An instance of our list structure
52 * @cl: private data of the file object
54 void mei_io_list_flush(struct mei_cl_cb
*list
, struct mei_cl
*cl
)
56 struct mei_cl_cb
*pos
;
57 struct mei_cl_cb
*next
;
59 list_for_each_entry_safe(pos
, next
, &list
->list
, list
) {
61 if (mei_cl_cmp_id(cl
, pos
->cl
))
67 * mei_cl_flush_queues - flushes queue lists belonging to cl.
69 * @dev: the device structure
70 * @cl: private data of the file object
72 int mei_cl_flush_queues(struct mei_cl
*cl
)
77 dev_dbg(&cl
->dev
->pdev
->dev
, "remove list entry belonging to cl\n");
78 mei_io_list_flush(&cl
->dev
->read_list
, cl
);
79 mei_io_list_flush(&cl
->dev
->write_list
, cl
);
80 mei_io_list_flush(&cl
->dev
->write_waiting_list
, cl
);
81 mei_io_list_flush(&cl
->dev
->ctrl_wr_list
, cl
);
82 mei_io_list_flush(&cl
->dev
->ctrl_rd_list
, cl
);
83 mei_io_list_flush(&cl
->dev
->amthif_cmd_list
, cl
);
84 mei_io_list_flush(&cl
->dev
->amthif_rd_complete_list
, cl
);
91 * init_mei_device - allocates and initializes the mei device structure
93 * @pdev: The pci device structure
95 * returns The mei_device_device pointer on success, NULL on failure.
97 struct mei_device
*mei_device_init(struct pci_dev
*pdev
)
99 struct mei_device
*dev
;
101 dev
= kzalloc(sizeof(struct mei_device
), GFP_KERNEL
);
105 /* setup our list array */
106 INIT_LIST_HEAD(&dev
->file_list
);
107 INIT_LIST_HEAD(&dev
->wd_cl
.link
);
108 INIT_LIST_HEAD(&dev
->iamthif_cl
.link
);
109 mutex_init(&dev
->device_lock
);
110 init_waitqueue_head(&dev
->wait_recvd_msg
);
111 init_waitqueue_head(&dev
->wait_stop_wd
);
112 dev
->dev_state
= MEI_DEV_INITIALIZING
;
113 dev
->iamthif_state
= MEI_IAMTHIF_IDLE
;
115 mei_io_list_init(&dev
->read_list
);
116 mei_io_list_init(&dev
->write_list
);
117 mei_io_list_init(&dev
->write_waiting_list
);
118 mei_io_list_init(&dev
->ctrl_wr_list
);
119 mei_io_list_init(&dev
->ctrl_rd_list
);
120 mei_io_list_init(&dev
->amthif_cmd_list
);
121 mei_io_list_init(&dev
->amthif_rd_complete_list
);
127 * mei_hw_init - initializes host and fw to start work.
129 * @dev: the device structure
131 * returns 0 on success, <0 on failure.
133 int mei_hw_init(struct mei_device
*dev
)
138 mutex_lock(&dev
->device_lock
);
140 dev
->host_hw_state
= mei_hcsr_read(dev
);
141 dev
->me_hw_state
= mei_mecsr_read(dev
);
142 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
143 dev
->host_hw_state
, dev
->me_hw_state
);
145 /* acknowledge interrupt and stop interupts */
146 mei_clear_interrupts(dev
);
148 /* Doesn't change in runtime */
149 dev
->hbuf_depth
= (dev
->host_hw_state
& H_CBD
) >> 24;
151 dev
->recvd_msg
= false;
152 dev_dbg(&dev
->pdev
->dev
, "reset in start the mei device.\n");
156 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
157 dev
->host_hw_state
, dev
->me_hw_state
);
159 /* wait for ME to turn on ME_RDY */
160 if (!dev
->recvd_msg
) {
161 mutex_unlock(&dev
->device_lock
);
162 err
= wait_event_interruptible_timeout(dev
->wait_recvd_msg
,
164 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT
));
165 mutex_lock(&dev
->device_lock
);
168 if (err
<= 0 && !dev
->recvd_msg
) {
169 dev
->dev_state
= MEI_DEV_DISABLED
;
170 dev_dbg(&dev
->pdev
->dev
,
171 "wait_event_interruptible_timeout failed"
172 "on wait for ME to turn on ME_RDY.\n");
177 if (!(((dev
->host_hw_state
& H_RDY
) == H_RDY
) &&
178 ((dev
->me_hw_state
& ME_RDY_HRA
) == ME_RDY_HRA
))) {
179 dev
->dev_state
= MEI_DEV_DISABLED
;
180 dev_dbg(&dev
->pdev
->dev
,
181 "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
182 dev
->host_hw_state
, dev
->me_hw_state
);
184 if (!(dev
->host_hw_state
& H_RDY
))
185 dev_dbg(&dev
->pdev
->dev
, "host turn off H_RDY.\n");
187 if (!(dev
->me_hw_state
& ME_RDY_HRA
))
188 dev_dbg(&dev
->pdev
->dev
, "ME turn off ME_RDY.\n");
190 dev_err(&dev
->pdev
->dev
, "link layer initialization failed.\n");
195 if (dev
->version
.major_version
!= HBM_MAJOR_VERSION
||
196 dev
->version
.minor_version
!= HBM_MINOR_VERSION
) {
197 dev_dbg(&dev
->pdev
->dev
, "MEI start failed.\n");
202 dev
->recvd_msg
= false;
203 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
204 dev
->host_hw_state
, dev
->me_hw_state
);
205 dev_dbg(&dev
->pdev
->dev
, "ME turn on ME_RDY and host turn on H_RDY.\n");
206 dev_dbg(&dev
->pdev
->dev
, "link layer has been established.\n");
207 dev_dbg(&dev
->pdev
->dev
, "MEI start success.\n");
211 mutex_unlock(&dev
->device_lock
);
216 * mei_hw_reset - resets fw via mei csr register.
218 * @dev: the device structure
219 * @interrupts_enabled: if interrupt should be enabled after reset.
221 static void mei_hw_reset(struct mei_device
*dev
, int interrupts_enabled
)
223 dev
->host_hw_state
|= (H_RST
| H_IG
);
225 if (interrupts_enabled
)
226 mei_enable_interrupts(dev
);
228 mei_disable_interrupts(dev
);
232 * mei_reset - resets host and fw.
234 * @dev: the device structure
235 * @interrupts_enabled: if interrupt should be enabled after reset.
237 void mei_reset(struct mei_device
*dev
, int interrupts_enabled
)
239 struct mei_cl
*cl_pos
= NULL
;
240 struct mei_cl
*cl_next
= NULL
;
241 struct mei_cl_cb
*cb_pos
= NULL
;
242 struct mei_cl_cb
*cb_next
= NULL
;
245 if (dev
->dev_state
== MEI_DEV_RECOVERING_FROM_RESET
) {
246 dev
->need_reset
= true;
250 unexpected
= (dev
->dev_state
!= MEI_DEV_INITIALIZING
&&
251 dev
->dev_state
!= MEI_DEV_DISABLED
&&
252 dev
->dev_state
!= MEI_DEV_POWER_DOWN
&&
253 dev
->dev_state
!= MEI_DEV_POWER_UP
);
255 dev
->host_hw_state
= mei_hcsr_read(dev
);
257 dev_dbg(&dev
->pdev
->dev
, "before reset host_hw_state = 0x%08x.\n",
260 mei_hw_reset(dev
, interrupts_enabled
);
262 dev
->host_hw_state
&= ~H_RST
;
263 dev
->host_hw_state
|= H_IG
;
267 dev_dbg(&dev
->pdev
->dev
, "currently saved host_hw_state = 0x%08x.\n",
270 dev
->need_reset
= false;
272 if (dev
->dev_state
!= MEI_DEV_INITIALIZING
) {
273 if (dev
->dev_state
!= MEI_DEV_DISABLED
&&
274 dev
->dev_state
!= MEI_DEV_POWER_DOWN
)
275 dev
->dev_state
= MEI_DEV_RESETING
;
277 list_for_each_entry_safe(cl_pos
,
278 cl_next
, &dev
->file_list
, link
) {
279 cl_pos
->state
= MEI_FILE_DISCONNECTED
;
280 cl_pos
->mei_flow_ctrl_creds
= 0;
281 cl_pos
->read_cb
= NULL
;
282 cl_pos
->timer_count
= 0;
284 /* remove entry if already in list */
285 dev_dbg(&dev
->pdev
->dev
, "remove iamthif and wd from the file list.\n");
286 mei_me_cl_unlink(dev
, &dev
->wd_cl
);
288 mei_me_cl_unlink(dev
, &dev
->iamthif_cl
);
290 mei_amthif_reset_params(dev
);
291 memset(&dev
->wr_ext_msg
, 0, sizeof(dev
->wr_ext_msg
));
294 dev
->me_clients_num
= 0;
296 dev
->wd_pending
= false;
298 /* update the state of the registers after reset */
299 dev
->host_hw_state
= mei_hcsr_read(dev
);
300 dev
->me_hw_state
= mei_mecsr_read(dev
);
302 dev_dbg(&dev
->pdev
->dev
, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
303 dev
->host_hw_state
, dev
->me_hw_state
);
306 dev_warn(&dev
->pdev
->dev
, "unexpected reset: dev_state = %s\n",
307 mei_dev_state_str(dev
->dev_state
));
309 /* Wake up all readings so they can be interrupted */
310 list_for_each_entry_safe(cl_pos
, cl_next
, &dev
->file_list
, link
) {
311 if (waitqueue_active(&cl_pos
->rx_wait
)) {
312 dev_dbg(&dev
->pdev
->dev
, "Waking up client!\n");
313 wake_up_interruptible(&cl_pos
->rx_wait
);
316 /* remove all waiting requests */
317 list_for_each_entry_safe(cb_pos
, cb_next
, &dev
->write_list
.list
, list
) {
318 list_del(&cb_pos
->list
);
319 mei_io_cb_free(cb_pos
);
325 * allocate_me_clients_storage - allocates storage for me clients
327 * @dev: the device structure
331 void mei_allocate_me_clients_storage(struct mei_device
*dev
)
333 struct mei_me_client
*clients
;
336 /* count how many ME clients we have */
337 for_each_set_bit(b
, dev
->me_clients_map
, MEI_CLIENTS_MAX
)
338 dev
->me_clients_num
++;
340 if (dev
->me_clients_num
<= 0)
344 if (dev
->me_clients
!= NULL
) {
345 kfree(dev
->me_clients
);
346 dev
->me_clients
= NULL
;
348 dev_dbg(&dev
->pdev
->dev
, "memory allocation for ME clients size=%zd.\n",
349 dev
->me_clients_num
* sizeof(struct mei_me_client
));
350 /* allocate storage for ME clients representation */
351 clients
= kcalloc(dev
->me_clients_num
,
352 sizeof(struct mei_me_client
), GFP_KERNEL
);
354 dev_dbg(&dev
->pdev
->dev
, "memory allocation for ME clients failed.\n");
355 dev
->dev_state
= MEI_DEV_RESETING
;
359 dev
->me_clients
= clients
;
363 void mei_host_client_init(struct work_struct
*work
)
365 struct mei_device
*dev
= container_of(work
,
366 struct mei_device
, init_work
);
367 struct mei_client_properties
*client_props
;
370 mutex_lock(&dev
->device_lock
);
372 bitmap_zero(dev
->host_clients_map
, MEI_CLIENTS_MAX
);
373 dev
->open_handle_count
= 0;
376 * Reserving the first three client IDs
377 * 0: Reserved for MEI Bus Message communications
378 * 1: Reserved for Watchdog
379 * 2: Reserved for AMTHI
381 bitmap_set(dev
->host_clients_map
, 0, 3);
383 for (i
= 0; i
< dev
->me_clients_num
; i
++) {
384 client_props
= &dev
->me_clients
[i
].props
;
386 if (!uuid_le_cmp(client_props
->protocol_name
, mei_amthi_guid
))
387 mei_amthif_host_init(dev
);
388 else if (!uuid_le_cmp(client_props
->protocol_name
, mei_wd_guid
))
389 mei_wd_host_init(dev
);
392 dev
->dev_state
= MEI_DEV_ENABLED
;
394 mutex_unlock(&dev
->device_lock
);
399 * mei_init_file_private - initializes private file structure.
401 * @priv: private file structure to be initialized
402 * @file: the file structure
404 void mei_cl_init(struct mei_cl
*priv
, struct mei_device
*dev
)
406 memset(priv
, 0, sizeof(struct mei_cl
));
407 init_waitqueue_head(&priv
->wait
);
408 init_waitqueue_head(&priv
->rx_wait
);
409 init_waitqueue_head(&priv
->tx_wait
);
410 INIT_LIST_HEAD(&priv
->link
);
411 priv
->reading_state
= MEI_IDLE
;
412 priv
->writing_state
= MEI_IDLE
;
416 int mei_me_cl_by_uuid(const struct mei_device
*dev
, const uuid_le
*cuuid
)
418 int i
, res
= -ENOENT
;
420 for (i
= 0; i
< dev
->me_clients_num
; ++i
)
421 if (uuid_le_cmp(*cuuid
,
422 dev
->me_clients
[i
].props
.protocol_name
) == 0) {
432 * mei_me_cl_link - create link between host and me clinet and add
435 * @dev: the device structure
436 * @cl: link between me and host client assocated with opened file descriptor
437 * @cuuid: uuid of ME client
438 * @client_id: id of the host client
440 * returns ME client index if ME client
441 * -EINVAL on incorrect values
442 * -ENONET if client not found
444 int mei_me_cl_link(struct mei_device
*dev
, struct mei_cl
*cl
,
445 const uuid_le
*cuuid
, u8 host_cl_id
)
449 if (!dev
|| !cl
|| !cuuid
)
452 /* check for valid client id */
453 i
= mei_me_cl_by_uuid(dev
, cuuid
);
455 cl
->me_client_id
= dev
->me_clients
[i
].client_id
;
456 cl
->state
= MEI_FILE_CONNECTING
;
457 cl
->host_client_id
= host_cl_id
;
459 list_add_tail(&cl
->link
, &dev
->file_list
);
466 * mei_me_cl_unlink - remove me_cl from the list
468 * @dev: the device structure
469 * @host_client_id: host client id to be removed
471 void mei_me_cl_unlink(struct mei_device
*dev
, struct mei_cl
*cl
)
473 struct mei_cl
*pos
, *next
;
474 list_for_each_entry_safe(pos
, next
, &dev
->file_list
, link
) {
475 if (cl
->host_client_id
== pos
->host_client_id
) {
476 dev_dbg(&dev
->pdev
->dev
, "remove host client = %d, ME client = %d\n",
477 pos
->host_client_id
, pos
->me_client_id
);
478 list_del_init(&pos
->link
);
485 * mei_alloc_file_private - allocates a private file structure and sets it up.
486 * @file: the file structure
488 * returns The allocated file or NULL on failure
490 struct mei_cl
*mei_cl_allocate(struct mei_device
*dev
)
494 cl
= kmalloc(sizeof(struct mei_cl
), GFP_KERNEL
);
498 mei_cl_init(cl
, dev
);
506 * mei_disconnect_host_client - sends disconnect message to fw from host client.
508 * @dev: the device structure
509 * @cl: private data of the file object
511 * Locking: called under "dev->device_lock" lock
513 * returns 0 on success, <0 on failure.
515 int mei_disconnect_host_client(struct mei_device
*dev
, struct mei_cl
*cl
)
517 struct mei_cl_cb
*cb
;
523 if (cl
->state
!= MEI_FILE_DISCONNECTING
)
526 cb
= mei_io_cb_init(cl
, NULL
);
530 cb
->fop_type
= MEI_FOP_CLOSE
;
531 if (dev
->mei_host_buffer_is_empty
) {
532 dev
->mei_host_buffer_is_empty
= false;
533 if (mei_hbm_cl_disconnect_req(dev
, cl
)) {
535 dev_err(&dev
->pdev
->dev
, "failed to disconnect.\n");
538 mdelay(10); /* Wait for hardware disconnection ready */
539 list_add_tail(&cb
->list
, &dev
->ctrl_rd_list
.list
);
541 dev_dbg(&dev
->pdev
->dev
, "add disconnect cb to control write list\n");
542 list_add_tail(&cb
->list
, &dev
->ctrl_wr_list
.list
);
545 mutex_unlock(&dev
->device_lock
);
547 err
= wait_event_timeout(dev
->wait_recvd_msg
,
548 MEI_FILE_DISCONNECTED
== cl
->state
,
549 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT
));
551 mutex_lock(&dev
->device_lock
);
552 if (MEI_FILE_DISCONNECTED
== cl
->state
) {
554 dev_dbg(&dev
->pdev
->dev
, "successfully disconnected from FW client.\n");
557 if (MEI_FILE_DISCONNECTED
!= cl
->state
)
558 dev_dbg(&dev
->pdev
->dev
, "wrong status client disconnect.\n");
561 dev_dbg(&dev
->pdev
->dev
,
562 "wait failed disconnect err=%08x\n",
565 dev_dbg(&dev
->pdev
->dev
, "failed to disconnect from FW client.\n");
568 mei_io_list_flush(&dev
->ctrl_rd_list
, cl
);
569 mei_io_list_flush(&dev
->ctrl_wr_list
, cl
);