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/export.h>
18 #include <linux/pci.h>
19 #include <linux/sched.h>
20 #include <linux/wait.h>
21 #include <linux/delay.h>
23 #include <linux/mei.h>
29 const char *mei_dev_state_str(int state
)
31 #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
33 MEI_DEV_STATE(INITIALIZING
);
34 MEI_DEV_STATE(INIT_CLIENTS
);
35 MEI_DEV_STATE(ENABLED
);
36 MEI_DEV_STATE(RESETING
);
37 MEI_DEV_STATE(DISABLED
);
38 MEI_DEV_STATE(POWER_DOWN
);
39 MEI_DEV_STATE(POWER_UP
);
46 void mei_device_init(struct mei_device
*dev
)
48 /* setup our list array */
49 INIT_LIST_HEAD(&dev
->file_list
);
50 INIT_LIST_HEAD(&dev
->device_list
);
51 mutex_init(&dev
->device_lock
);
52 init_waitqueue_head(&dev
->wait_hw_ready
);
53 init_waitqueue_head(&dev
->wait_recvd_msg
);
54 init_waitqueue_head(&dev
->wait_stop_wd
);
55 dev
->dev_state
= MEI_DEV_INITIALIZING
;
57 mei_io_list_init(&dev
->read_list
);
58 mei_io_list_init(&dev
->write_list
);
59 mei_io_list_init(&dev
->write_waiting_list
);
60 mei_io_list_init(&dev
->ctrl_wr_list
);
61 mei_io_list_init(&dev
->ctrl_rd_list
);
63 INIT_DELAYED_WORK(&dev
->timer_work
, mei_timer
);
64 INIT_WORK(&dev
->init_work
, mei_host_client_init
);
66 INIT_LIST_HEAD(&dev
->wd_cl
.link
);
67 INIT_LIST_HEAD(&dev
->iamthif_cl
.link
);
68 mei_io_list_init(&dev
->amthif_cmd_list
);
69 mei_io_list_init(&dev
->amthif_rd_complete_list
);
72 EXPORT_SYMBOL_GPL(mei_device_init
);
75 * mei_start - initializes host and fw to start work.
77 * @dev: the device structure
79 * returns 0 on success, <0 on failure.
81 int mei_start(struct mei_device
*dev
)
85 mutex_lock(&dev
->device_lock
);
87 /* acknowledge interrupt and stop interupts */
88 mei_clear_interrupts(dev
);
92 dev
->recvd_msg
= false;
93 dev_dbg(&dev
->pdev
->dev
, "reset in start the mei device.\n");
97 /* wait for ME to turn on ME_RDY */
98 if (!dev
->recvd_msg
) {
99 mutex_unlock(&dev
->device_lock
);
100 ret
= wait_event_interruptible_timeout(dev
->wait_recvd_msg
,
102 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT
));
103 mutex_lock(&dev
->device_lock
);
106 if (ret
<= 0 && !dev
->recvd_msg
) {
107 dev
->dev_state
= MEI_DEV_DISABLED
;
108 dev_dbg(&dev
->pdev
->dev
,
109 "wait_event_interruptible_timeout failed"
110 "on wait for ME to turn on ME_RDY.\n");
115 if (!mei_host_is_ready(dev
)) {
116 dev_err(&dev
->pdev
->dev
, "host is not ready.\n");
120 if (!mei_hw_is_ready(dev
)) {
121 dev_err(&dev
->pdev
->dev
, "ME is not ready.\n");
125 if (dev
->version
.major_version
!= HBM_MAJOR_VERSION
||
126 dev
->version
.minor_version
!= HBM_MINOR_VERSION
) {
127 dev_dbg(&dev
->pdev
->dev
, "MEI start failed.\n");
131 dev
->recvd_msg
= false;
132 dev_dbg(&dev
->pdev
->dev
, "link layer has been established.\n");
134 mutex_unlock(&dev
->device_lock
);
137 dev_err(&dev
->pdev
->dev
, "link layer initialization failed.\n");
138 dev
->dev_state
= MEI_DEV_DISABLED
;
139 mutex_unlock(&dev
->device_lock
);
142 EXPORT_SYMBOL_GPL(mei_start
);
145 * mei_reset - resets host and fw.
147 * @dev: the device structure
148 * @interrupts_enabled: if interrupt should be enabled after reset.
150 void mei_reset(struct mei_device
*dev
, int interrupts_enabled
)
154 unexpected
= (dev
->dev_state
!= MEI_DEV_INITIALIZING
&&
155 dev
->dev_state
!= MEI_DEV_DISABLED
&&
156 dev
->dev_state
!= MEI_DEV_POWER_DOWN
&&
157 dev
->dev_state
!= MEI_DEV_POWER_UP
);
159 mei_hw_reset(dev
, interrupts_enabled
);
162 if (dev
->dev_state
!= MEI_DEV_INITIALIZING
) {
163 if (dev
->dev_state
!= MEI_DEV_DISABLED
&&
164 dev
->dev_state
!= MEI_DEV_POWER_DOWN
)
165 dev
->dev_state
= MEI_DEV_RESETING
;
167 mei_cl_all_disconnect(dev
);
169 /* remove entry if already in list */
170 dev_dbg(&dev
->pdev
->dev
, "remove iamthif and wd from the file list.\n");
171 mei_cl_unlink(&dev
->wd_cl
);
172 if (dev
->open_handle_count
> 0)
173 dev
->open_handle_count
--;
174 mei_cl_unlink(&dev
->iamthif_cl
);
175 if (dev
->open_handle_count
> 0)
176 dev
->open_handle_count
--;
178 mei_amthif_reset_params(dev
);
179 memset(&dev
->wr_ext_msg
, 0, sizeof(dev
->wr_ext_msg
));
182 dev
->me_clients_num
= 0;
184 dev
->wd_pending
= false;
187 dev_warn(&dev
->pdev
->dev
, "unexpected reset: dev_state = %s\n",
188 mei_dev_state_str(dev
->dev_state
));
190 if (!interrupts_enabled
) {
191 dev_dbg(&dev
->pdev
->dev
, "intr not enabled end of reset\n");
197 dev_dbg(&dev
->pdev
->dev
, "link is established start sending messages.\n");
198 /* link is established * start sending messages. */
200 dev
->dev_state
= MEI_DEV_INIT_CLIENTS
;
202 mei_hbm_start_req(dev
);
204 /* wake up all readings so they can be interrupted */
205 mei_cl_all_read_wakeup(dev
);
207 /* remove all waiting requests */
208 mei_cl_all_write_clear(dev
);
210 EXPORT_SYMBOL_GPL(mei_reset
);
212 void mei_stop(struct mei_device
*dev
)
214 dev_dbg(&dev
->pdev
->dev
, "stopping the device.\n");
216 mutex_lock(&dev
->device_lock
);
218 cancel_delayed_work(&dev
->timer_work
);
222 dev
->dev_state
= MEI_DEV_POWER_DOWN
;
225 mutex_unlock(&dev
->device_lock
);
227 flush_scheduled_work();
229 mei_watchdog_unregister(dev
);
231 EXPORT_SYMBOL_GPL(mei_stop
);
This page took 0.037006 seconds and 6 git commands to generate.