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
);
49 * init_mei_device - allocates and initializes the mei device structure
51 * @pdev: The pci device structure
53 * returns The mei_device_device pointer on success, NULL on failure.
55 struct mei_device
*mei_device_init(struct pci_dev
*pdev
)
57 struct mei_device
*dev
;
59 dev
= kzalloc(sizeof(struct mei_device
), GFP_KERNEL
);
63 /* setup our list array */
64 INIT_LIST_HEAD(&dev
->file_list
);
65 INIT_LIST_HEAD(&dev
->wd_cl
.link
);
66 INIT_LIST_HEAD(&dev
->iamthif_cl
.link
);
67 mutex_init(&dev
->device_lock
);
68 init_waitqueue_head(&dev
->wait_recvd_msg
);
69 init_waitqueue_head(&dev
->wait_stop_wd
);
70 dev
->dev_state
= MEI_DEV_INITIALIZING
;
72 mei_io_list_init(&dev
->read_list
);
73 mei_io_list_init(&dev
->write_list
);
74 mei_io_list_init(&dev
->write_waiting_list
);
75 mei_io_list_init(&dev
->ctrl_wr_list
);
76 mei_io_list_init(&dev
->ctrl_rd_list
);
77 mei_io_list_init(&dev
->amthif_cmd_list
);
78 mei_io_list_init(&dev
->amthif_rd_complete_list
);
84 * mei_hw_init - initializes host and fw to start work.
86 * @dev: the device structure
88 * returns 0 on success, <0 on failure.
90 int mei_hw_init(struct mei_device
*dev
)
95 mutex_lock(&dev
->device_lock
);
97 dev
->host_hw_state
= mei_hcsr_read(dev
);
98 dev
->me_hw_state
= mei_mecsr_read(dev
);
99 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
100 dev
->host_hw_state
, dev
->me_hw_state
);
102 /* acknowledge interrupt and stop interupts */
103 mei_clear_interrupts(dev
);
105 /* Doesn't change in runtime */
106 dev
->hbuf_depth
= (dev
->host_hw_state
& H_CBD
) >> 24;
108 dev
->recvd_msg
= false;
109 dev_dbg(&dev
->pdev
->dev
, "reset in start the mei device.\n");
113 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
114 dev
->host_hw_state
, dev
->me_hw_state
);
116 /* wait for ME to turn on ME_RDY */
117 if (!dev
->recvd_msg
) {
118 mutex_unlock(&dev
->device_lock
);
119 err
= wait_event_interruptible_timeout(dev
->wait_recvd_msg
,
121 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT
));
122 mutex_lock(&dev
->device_lock
);
125 if (err
<= 0 && !dev
->recvd_msg
) {
126 dev
->dev_state
= MEI_DEV_DISABLED
;
127 dev_dbg(&dev
->pdev
->dev
,
128 "wait_event_interruptible_timeout failed"
129 "on wait for ME to turn on ME_RDY.\n");
134 if (!(((dev
->host_hw_state
& H_RDY
) == H_RDY
) &&
135 ((dev
->me_hw_state
& ME_RDY_HRA
) == ME_RDY_HRA
))) {
136 dev
->dev_state
= MEI_DEV_DISABLED
;
137 dev_dbg(&dev
->pdev
->dev
,
138 "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
139 dev
->host_hw_state
, dev
->me_hw_state
);
141 if (!(dev
->host_hw_state
& H_RDY
))
142 dev_dbg(&dev
->pdev
->dev
, "host turn off H_RDY.\n");
144 if (!(dev
->me_hw_state
& ME_RDY_HRA
))
145 dev_dbg(&dev
->pdev
->dev
, "ME turn off ME_RDY.\n");
147 dev_err(&dev
->pdev
->dev
, "link layer initialization failed.\n");
152 if (dev
->version
.major_version
!= HBM_MAJOR_VERSION
||
153 dev
->version
.minor_version
!= HBM_MINOR_VERSION
) {
154 dev_dbg(&dev
->pdev
->dev
, "MEI start failed.\n");
159 dev
->recvd_msg
= false;
160 dev_dbg(&dev
->pdev
->dev
, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
161 dev
->host_hw_state
, dev
->me_hw_state
);
162 dev_dbg(&dev
->pdev
->dev
, "ME turn on ME_RDY and host turn on H_RDY.\n");
163 dev_dbg(&dev
->pdev
->dev
, "link layer has been established.\n");
164 dev_dbg(&dev
->pdev
->dev
, "MEI start success.\n");
168 mutex_unlock(&dev
->device_lock
);
173 * mei_hw_reset - resets fw via mei csr register.
175 * @dev: the device structure
176 * @interrupts_enabled: if interrupt should be enabled after reset.
178 static void mei_hw_reset(struct mei_device
*dev
, int interrupts_enabled
)
180 dev
->host_hw_state
|= (H_RST
| H_IG
);
182 if (interrupts_enabled
)
183 mei_enable_interrupts(dev
);
185 mei_disable_interrupts(dev
);
189 * mei_reset - resets host and fw.
191 * @dev: the device structure
192 * @interrupts_enabled: if interrupt should be enabled after reset.
194 void mei_reset(struct mei_device
*dev
, int interrupts_enabled
)
196 struct mei_cl
*cl_pos
= NULL
;
197 struct mei_cl
*cl_next
= NULL
;
198 struct mei_cl_cb
*cb_pos
= NULL
;
199 struct mei_cl_cb
*cb_next
= NULL
;
202 if (dev
->dev_state
== MEI_DEV_RECOVERING_FROM_RESET
)
205 unexpected
= (dev
->dev_state
!= MEI_DEV_INITIALIZING
&&
206 dev
->dev_state
!= MEI_DEV_DISABLED
&&
207 dev
->dev_state
!= MEI_DEV_POWER_DOWN
&&
208 dev
->dev_state
!= MEI_DEV_POWER_UP
);
210 dev
->host_hw_state
= mei_hcsr_read(dev
);
212 dev_dbg(&dev
->pdev
->dev
, "before reset host_hw_state = 0x%08x.\n",
215 mei_hw_reset(dev
, interrupts_enabled
);
217 dev
->host_hw_state
&= ~H_RST
;
218 dev
->host_hw_state
|= H_IG
;
222 dev_dbg(&dev
->pdev
->dev
, "currently saved host_hw_state = 0x%08x.\n",
225 if (dev
->dev_state
!= MEI_DEV_INITIALIZING
) {
226 if (dev
->dev_state
!= MEI_DEV_DISABLED
&&
227 dev
->dev_state
!= MEI_DEV_POWER_DOWN
)
228 dev
->dev_state
= MEI_DEV_RESETING
;
230 list_for_each_entry_safe(cl_pos
,
231 cl_next
, &dev
->file_list
, link
) {
232 cl_pos
->state
= MEI_FILE_DISCONNECTED
;
233 cl_pos
->mei_flow_ctrl_creds
= 0;
234 cl_pos
->read_cb
= NULL
;
235 cl_pos
->timer_count
= 0;
237 /* remove entry if already in list */
238 dev_dbg(&dev
->pdev
->dev
, "remove iamthif and wd from the file list.\n");
239 mei_cl_unlink(&dev
->wd_cl
);
240 if (dev
->open_handle_count
> 0)
241 dev
->open_handle_count
--;
242 mei_cl_unlink(&dev
->iamthif_cl
);
243 if (dev
->open_handle_count
> 0)
244 dev
->open_handle_count
--;
246 mei_amthif_reset_params(dev
);
247 memset(&dev
->wr_ext_msg
, 0, sizeof(dev
->wr_ext_msg
));
250 dev
->me_clients_num
= 0;
252 dev
->wd_pending
= false;
254 /* update the state of the registers after reset */
255 dev
->host_hw_state
= mei_hcsr_read(dev
);
256 dev
->me_hw_state
= mei_mecsr_read(dev
);
258 dev_dbg(&dev
->pdev
->dev
, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
259 dev
->host_hw_state
, dev
->me_hw_state
);
262 dev_warn(&dev
->pdev
->dev
, "unexpected reset: dev_state = %s\n",
263 mei_dev_state_str(dev
->dev_state
));
265 /* Wake up all readings so they can be interrupted */
266 list_for_each_entry_safe(cl_pos
, cl_next
, &dev
->file_list
, link
) {
267 if (waitqueue_active(&cl_pos
->rx_wait
)) {
268 dev_dbg(&dev
->pdev
->dev
, "Waking up client!\n");
269 wake_up_interruptible(&cl_pos
->rx_wait
);
272 /* remove all waiting requests */
273 list_for_each_entry_safe(cb_pos
, cb_next
, &dev
->write_list
.list
, list
) {
274 list_del(&cb_pos
->list
);
275 mei_io_cb_free(cb_pos
);