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(RESETTING
);
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
)
83 mutex_lock(&dev
->device_lock
);
85 /* acknowledge interrupt and stop interupts */
86 mei_clear_interrupts(dev
);
90 dev_dbg(&dev
->pdev
->dev
, "reset in start the mei device.\n");
94 if (mei_hbm_start_wait(dev
)) {
95 dev_err(&dev
->pdev
->dev
, "HBM haven't started");
99 if (!mei_host_is_ready(dev
)) {
100 dev_err(&dev
->pdev
->dev
, "host is not ready.\n");
104 if (!mei_hw_is_ready(dev
)) {
105 dev_err(&dev
->pdev
->dev
, "ME is not ready.\n");
109 if (dev
->version
.major_version
!= HBM_MAJOR_VERSION
||
110 dev
->version
.minor_version
!= HBM_MINOR_VERSION
) {
111 dev_dbg(&dev
->pdev
->dev
, "MEI start failed.\n");
115 dev_dbg(&dev
->pdev
->dev
, "link layer has been established.\n");
117 mutex_unlock(&dev
->device_lock
);
120 dev_err(&dev
->pdev
->dev
, "link layer initialization failed.\n");
121 dev
->dev_state
= MEI_DEV_DISABLED
;
122 mutex_unlock(&dev
->device_lock
);
125 EXPORT_SYMBOL_GPL(mei_start
);
128 * mei_reset - resets host and fw.
130 * @dev: the device structure
131 * @interrupts_enabled: if interrupt should be enabled after reset.
133 void mei_reset(struct mei_device
*dev
, int interrupts_enabled
)
137 unexpected
= (dev
->dev_state
!= MEI_DEV_INITIALIZING
&&
138 dev
->dev_state
!= MEI_DEV_DISABLED
&&
139 dev
->dev_state
!= MEI_DEV_POWER_DOWN
&&
140 dev
->dev_state
!= MEI_DEV_POWER_UP
);
142 mei_hw_reset(dev
, interrupts_enabled
);
144 dev
->hbm_state
= MEI_HBM_IDLE
;
146 if (dev
->dev_state
!= MEI_DEV_INITIALIZING
) {
147 if (dev
->dev_state
!= MEI_DEV_DISABLED
&&
148 dev
->dev_state
!= MEI_DEV_POWER_DOWN
)
149 dev
->dev_state
= MEI_DEV_RESETTING
;
151 mei_cl_all_disconnect(dev
);
153 /* remove entry if already in list */
154 dev_dbg(&dev
->pdev
->dev
, "remove iamthif and wd from the file list.\n");
155 mei_cl_unlink(&dev
->wd_cl
);
156 if (dev
->open_handle_count
> 0)
157 dev
->open_handle_count
--;
158 mei_cl_unlink(&dev
->iamthif_cl
);
159 if (dev
->open_handle_count
> 0)
160 dev
->open_handle_count
--;
162 mei_amthif_reset_params(dev
);
163 memset(&dev
->wr_ext_msg
, 0, sizeof(dev
->wr_ext_msg
));
166 dev
->me_clients_num
= 0;
168 dev
->wd_pending
= false;
171 dev_warn(&dev
->pdev
->dev
, "unexpected reset: dev_state = %s\n",
172 mei_dev_state_str(dev
->dev_state
));
174 if (!interrupts_enabled
) {
175 dev_dbg(&dev
->pdev
->dev
, "intr not enabled end of reset\n");
181 dev_dbg(&dev
->pdev
->dev
, "link is established start sending messages.\n");
182 /* link is established * start sending messages. */
184 dev
->dev_state
= MEI_DEV_INIT_CLIENTS
;
186 mei_hbm_start_req(dev
);
188 /* wake up all readings so they can be interrupted */
189 mei_cl_all_read_wakeup(dev
);
191 /* remove all waiting requests */
192 mei_cl_all_write_clear(dev
);
194 EXPORT_SYMBOL_GPL(mei_reset
);
196 void mei_stop(struct mei_device
*dev
)
198 dev_dbg(&dev
->pdev
->dev
, "stopping the device.\n");
200 mutex_lock(&dev
->device_lock
);
202 cancel_delayed_work(&dev
->timer_work
);
208 dev
->dev_state
= MEI_DEV_POWER_DOWN
;
211 mutex_unlock(&dev
->device_lock
);
213 flush_scheduled_work();
215 mei_watchdog_unregister(dev
);
217 EXPORT_SYMBOL_GPL(mei_stop
);
This page took 0.034442 seconds and 5 git commands to generate.