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>
27 const char *mei_dev_state_str(int state
)
29 #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
31 MEI_DEV_STATE(INITIALIZING
);
32 MEI_DEV_STATE(INIT_CLIENTS
);
33 MEI_DEV_STATE(ENABLED
);
34 MEI_DEV_STATE(RESETING
);
35 MEI_DEV_STATE(DISABLED
);
36 MEI_DEV_STATE(RECOVERING_FROM_RESET
);
37 MEI_DEV_STATE(POWER_DOWN
);
38 MEI_DEV_STATE(POWER_UP
);
45 void mei_device_init(struct mei_device
*dev
)
47 /* setup our list array */
48 INIT_LIST_HEAD(&dev
->file_list
);
49 mutex_init(&dev
->device_lock
);
50 init_waitqueue_head(&dev
->wait_recvd_msg
);
51 init_waitqueue_head(&dev
->wait_stop_wd
);
52 dev
->dev_state
= MEI_DEV_INITIALIZING
;
54 mei_io_list_init(&dev
->read_list
);
55 mei_io_list_init(&dev
->write_list
);
56 mei_io_list_init(&dev
->write_waiting_list
);
57 mei_io_list_init(&dev
->ctrl_wr_list
);
58 mei_io_list_init(&dev
->ctrl_rd_list
);
62 * mei_hw_init - initializes host and fw to start work.
64 * @dev: the device structure
66 * returns 0 on success, <0 on failure.
68 int mei_hw_init(struct mei_device
*dev
)
72 mutex_lock(&dev
->device_lock
);
74 /* acknowledge interrupt and stop interupts */
75 mei_clear_interrupts(dev
);
79 dev
->recvd_msg
= false;
80 dev_dbg(&dev
->pdev
->dev
, "reset in start the mei device.\n");
84 /* wait for ME to turn on ME_RDY */
85 if (!dev
->recvd_msg
) {
86 mutex_unlock(&dev
->device_lock
);
87 ret
= wait_event_interruptible_timeout(dev
->wait_recvd_msg
,
89 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT
));
90 mutex_lock(&dev
->device_lock
);
93 if (ret
<= 0 && !dev
->recvd_msg
) {
94 dev
->dev_state
= MEI_DEV_DISABLED
;
95 dev_dbg(&dev
->pdev
->dev
,
96 "wait_event_interruptible_timeout failed"
97 "on wait for ME to turn on ME_RDY.\n");
102 if (!mei_host_is_ready(dev
)) {
103 dev_err(&dev
->pdev
->dev
, "host is not ready.\n");
107 if (!mei_hw_is_ready(dev
)) {
108 dev_err(&dev
->pdev
->dev
, "ME is not ready.\n");
112 if (dev
->version
.major_version
!= HBM_MAJOR_VERSION
||
113 dev
->version
.minor_version
!= HBM_MINOR_VERSION
) {
114 dev_dbg(&dev
->pdev
->dev
, "MEI start failed.\n");
118 dev
->recvd_msg
= false;
119 dev_dbg(&dev
->pdev
->dev
, "link layer has been established.\n");
121 mutex_unlock(&dev
->device_lock
);
124 dev_err(&dev
->pdev
->dev
, "link layer initialization failed.\n");
125 dev
->dev_state
= MEI_DEV_DISABLED
;
126 mutex_unlock(&dev
->device_lock
);
131 * mei_reset - resets host and fw.
133 * @dev: the device structure
134 * @interrupts_enabled: if interrupt should be enabled after reset.
136 void mei_reset(struct mei_device
*dev
, int interrupts_enabled
)
140 if (dev
->dev_state
== MEI_DEV_RECOVERING_FROM_RESET
)
143 unexpected
= (dev
->dev_state
!= MEI_DEV_INITIALIZING
&&
144 dev
->dev_state
!= MEI_DEV_DISABLED
&&
145 dev
->dev_state
!= MEI_DEV_POWER_DOWN
&&
146 dev
->dev_state
!= MEI_DEV_POWER_UP
);
148 mei_hw_reset(dev
, interrupts_enabled
);
151 if (dev
->dev_state
!= MEI_DEV_INITIALIZING
) {
152 if (dev
->dev_state
!= MEI_DEV_DISABLED
&&
153 dev
->dev_state
!= MEI_DEV_POWER_DOWN
)
154 dev
->dev_state
= MEI_DEV_RESETING
;
156 mei_cl_all_disconnect(dev
);
158 /* remove entry if already in list */
159 dev_dbg(&dev
->pdev
->dev
, "remove iamthif and wd from the file list.\n");
160 mei_cl_unlink(&dev
->wd_cl
);
161 if (dev
->open_handle_count
> 0)
162 dev
->open_handle_count
--;
163 mei_cl_unlink(&dev
->iamthif_cl
);
164 if (dev
->open_handle_count
> 0)
165 dev
->open_handle_count
--;
167 mei_amthif_reset_params(dev
);
168 memset(&dev
->wr_ext_msg
, 0, sizeof(dev
->wr_ext_msg
));
171 dev
->me_clients_num
= 0;
173 dev
->wd_pending
= false;
176 dev_warn(&dev
->pdev
->dev
, "unexpected reset: dev_state = %s\n",
177 mei_dev_state_str(dev
->dev_state
));
179 /* wake up all readings so they can be interrupted */
180 mei_cl_all_read_wakeup(dev
);
182 /* remove all waiting requests */
183 mei_cl_all_write_clear(dev
);