Commit 6c15a8516b8118eb19a59fd0bd22df41b9101c32

Authored by Alexander Usyskin
Committed by Greg Kroah-Hartman
1 parent f4c72c7030

mei: make device disabled on stop unconditionally

Set the internal device state to to disabled after hardware reset in stop flow.
This will cover cases when driver was not brought to disabled state because of
an error and in stop flow we wish not to retry the reset.

Cc: <stable@vger.kernel.org> #3.10+
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 2 additions and 0 deletions Inline Diff

drivers/misc/mei/init.c
1 /* 1 /*
2 * 2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver 3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation. 4 * Copyright (c) 2003-2012, Intel Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 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, 7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation. 8 * version 2, as published by the Free Software Foundation.
9 * 9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT 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 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details. 13 * more details.
14 * 14 *
15 */ 15 */
16 16
17 #include <linux/export.h> 17 #include <linux/export.h>
18 #include <linux/sched.h> 18 #include <linux/sched.h>
19 #include <linux/wait.h> 19 #include <linux/wait.h>
20 #include <linux/delay.h> 20 #include <linux/delay.h>
21 21
22 #include <linux/mei.h> 22 #include <linux/mei.h>
23 23
24 #include "mei_dev.h" 24 #include "mei_dev.h"
25 #include "hbm.h" 25 #include "hbm.h"
26 #include "client.h" 26 #include "client.h"
27 27
28 const char *mei_dev_state_str(int state) 28 const char *mei_dev_state_str(int state)
29 { 29 {
30 #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state 30 #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
31 switch (state) { 31 switch (state) {
32 MEI_DEV_STATE(INITIALIZING); 32 MEI_DEV_STATE(INITIALIZING);
33 MEI_DEV_STATE(INIT_CLIENTS); 33 MEI_DEV_STATE(INIT_CLIENTS);
34 MEI_DEV_STATE(ENABLED); 34 MEI_DEV_STATE(ENABLED);
35 MEI_DEV_STATE(RESETTING); 35 MEI_DEV_STATE(RESETTING);
36 MEI_DEV_STATE(DISABLED); 36 MEI_DEV_STATE(DISABLED);
37 MEI_DEV_STATE(POWER_DOWN); 37 MEI_DEV_STATE(POWER_DOWN);
38 MEI_DEV_STATE(POWER_UP); 38 MEI_DEV_STATE(POWER_UP);
39 default: 39 default:
40 return "unknown"; 40 return "unknown";
41 } 41 }
42 #undef MEI_DEV_STATE 42 #undef MEI_DEV_STATE
43 } 43 }
44 44
45 const char *mei_pg_state_str(enum mei_pg_state state) 45 const char *mei_pg_state_str(enum mei_pg_state state)
46 { 46 {
47 #define MEI_PG_STATE(state) case MEI_PG_##state: return #state 47 #define MEI_PG_STATE(state) case MEI_PG_##state: return #state
48 switch (state) { 48 switch (state) {
49 MEI_PG_STATE(OFF); 49 MEI_PG_STATE(OFF);
50 MEI_PG_STATE(ON); 50 MEI_PG_STATE(ON);
51 default: 51 default:
52 return "unknown"; 52 return "unknown";
53 } 53 }
54 #undef MEI_PG_STATE 54 #undef MEI_PG_STATE
55 } 55 }
56 56
57 /** 57 /**
58 * mei_fw_status2str - convert fw status registers to printable string 58 * mei_fw_status2str - convert fw status registers to printable string
59 * 59 *
60 * @fw_status: firmware status 60 * @fw_status: firmware status
61 * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ 61 * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
62 * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ 62 * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
63 * 63 *
64 * Return: number of bytes written or -EINVAL if buffer is to small 64 * Return: number of bytes written or -EINVAL if buffer is to small
65 */ 65 */
66 ssize_t mei_fw_status2str(struct mei_fw_status *fw_status, 66 ssize_t mei_fw_status2str(struct mei_fw_status *fw_status,
67 char *buf, size_t len) 67 char *buf, size_t len)
68 { 68 {
69 ssize_t cnt = 0; 69 ssize_t cnt = 0;
70 int i; 70 int i;
71 71
72 buf[0] = '\0'; 72 buf[0] = '\0';
73 73
74 if (len < MEI_FW_STATUS_STR_SZ) 74 if (len < MEI_FW_STATUS_STR_SZ)
75 return -EINVAL; 75 return -EINVAL;
76 76
77 for (i = 0; i < fw_status->count; i++) 77 for (i = 0; i < fw_status->count; i++)
78 cnt += scnprintf(buf + cnt, len - cnt, "%08X ", 78 cnt += scnprintf(buf + cnt, len - cnt, "%08X ",
79 fw_status->status[i]); 79 fw_status->status[i]);
80 80
81 /* drop last space */ 81 /* drop last space */
82 buf[cnt] = '\0'; 82 buf[cnt] = '\0';
83 return cnt; 83 return cnt;
84 } 84 }
85 EXPORT_SYMBOL_GPL(mei_fw_status2str); 85 EXPORT_SYMBOL_GPL(mei_fw_status2str);
86 86
87 /** 87 /**
88 * mei_cancel_work - Cancel mei background jobs 88 * mei_cancel_work - Cancel mei background jobs
89 * 89 *
90 * @dev: the device structure 90 * @dev: the device structure
91 */ 91 */
92 void mei_cancel_work(struct mei_device *dev) 92 void mei_cancel_work(struct mei_device *dev)
93 { 93 {
94 cancel_work_sync(&dev->init_work); 94 cancel_work_sync(&dev->init_work);
95 cancel_work_sync(&dev->reset_work); 95 cancel_work_sync(&dev->reset_work);
96 96
97 cancel_delayed_work(&dev->timer_work); 97 cancel_delayed_work(&dev->timer_work);
98 } 98 }
99 EXPORT_SYMBOL_GPL(mei_cancel_work); 99 EXPORT_SYMBOL_GPL(mei_cancel_work);
100 100
101 /** 101 /**
102 * mei_reset - resets host and fw. 102 * mei_reset - resets host and fw.
103 * 103 *
104 * @dev: the device structure 104 * @dev: the device structure
105 * 105 *
106 * Return: 0 on success or < 0 if the reset hasn't succeeded 106 * Return: 0 on success or < 0 if the reset hasn't succeeded
107 */ 107 */
108 int mei_reset(struct mei_device *dev) 108 int mei_reset(struct mei_device *dev)
109 { 109 {
110 enum mei_dev_state state = dev->dev_state; 110 enum mei_dev_state state = dev->dev_state;
111 bool interrupts_enabled; 111 bool interrupts_enabled;
112 int ret; 112 int ret;
113 113
114 if (state != MEI_DEV_INITIALIZING && 114 if (state != MEI_DEV_INITIALIZING &&
115 state != MEI_DEV_DISABLED && 115 state != MEI_DEV_DISABLED &&
116 state != MEI_DEV_POWER_DOWN && 116 state != MEI_DEV_POWER_DOWN &&
117 state != MEI_DEV_POWER_UP) { 117 state != MEI_DEV_POWER_UP) {
118 char fw_sts_str[MEI_FW_STATUS_STR_SZ]; 118 char fw_sts_str[MEI_FW_STATUS_STR_SZ];
119 119
120 mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ); 120 mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
121 dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", 121 dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
122 mei_dev_state_str(state), fw_sts_str); 122 mei_dev_state_str(state), fw_sts_str);
123 } 123 }
124 124
125 /* we're already in reset, cancel the init timer 125 /* we're already in reset, cancel the init timer
126 * if the reset was called due the hbm protocol error 126 * if the reset was called due the hbm protocol error
127 * we need to call it before hw start 127 * we need to call it before hw start
128 * so the hbm watchdog won't kick in 128 * so the hbm watchdog won't kick in
129 */ 129 */
130 mei_hbm_idle(dev); 130 mei_hbm_idle(dev);
131 131
132 /* enter reset flow */ 132 /* enter reset flow */
133 interrupts_enabled = state != MEI_DEV_POWER_DOWN; 133 interrupts_enabled = state != MEI_DEV_POWER_DOWN;
134 dev->dev_state = MEI_DEV_RESETTING; 134 dev->dev_state = MEI_DEV_RESETTING;
135 135
136 dev->reset_count++; 136 dev->reset_count++;
137 if (dev->reset_count > MEI_MAX_CONSEC_RESET) { 137 if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
138 dev_err(dev->dev, "reset: reached maximal consecutive resets: disabling the device\n"); 138 dev_err(dev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
139 dev->dev_state = MEI_DEV_DISABLED; 139 dev->dev_state = MEI_DEV_DISABLED;
140 return -ENODEV; 140 return -ENODEV;
141 } 141 }
142 142
143 ret = mei_hw_reset(dev, interrupts_enabled); 143 ret = mei_hw_reset(dev, interrupts_enabled);
144 /* fall through and remove the sw state even if hw reset has failed */ 144 /* fall through and remove the sw state even if hw reset has failed */
145 145
146 /* no need to clean up software state in case of power up */ 146 /* no need to clean up software state in case of power up */
147 if (state != MEI_DEV_INITIALIZING && 147 if (state != MEI_DEV_INITIALIZING &&
148 state != MEI_DEV_POWER_UP) { 148 state != MEI_DEV_POWER_UP) {
149 149
150 /* remove all waiting requests */ 150 /* remove all waiting requests */
151 mei_cl_all_write_clear(dev); 151 mei_cl_all_write_clear(dev);
152 152
153 mei_cl_all_disconnect(dev); 153 mei_cl_all_disconnect(dev);
154 154
155 /* wake up all readers and writers so they can be interrupted */ 155 /* wake up all readers and writers so they can be interrupted */
156 mei_cl_all_wakeup(dev); 156 mei_cl_all_wakeup(dev);
157 157
158 /* remove entry if already in list */ 158 /* remove entry if already in list */
159 dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n"); 159 dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n");
160 mei_cl_unlink(&dev->wd_cl); 160 mei_cl_unlink(&dev->wd_cl);
161 mei_cl_unlink(&dev->iamthif_cl); 161 mei_cl_unlink(&dev->iamthif_cl);
162 mei_amthif_reset_params(dev); 162 mei_amthif_reset_params(dev);
163 } 163 }
164 164
165 mei_hbm_reset(dev); 165 mei_hbm_reset(dev);
166 166
167 dev->rd_msg_hdr = 0; 167 dev->rd_msg_hdr = 0;
168 dev->wd_pending = false; 168 dev->wd_pending = false;
169 169
170 if (ret) { 170 if (ret) {
171 dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); 171 dev_err(dev->dev, "hw_reset failed ret = %d\n", ret);
172 return ret; 172 return ret;
173 } 173 }
174 174
175 if (state == MEI_DEV_POWER_DOWN) { 175 if (state == MEI_DEV_POWER_DOWN) {
176 dev_dbg(dev->dev, "powering down: end of reset\n"); 176 dev_dbg(dev->dev, "powering down: end of reset\n");
177 dev->dev_state = MEI_DEV_DISABLED; 177 dev->dev_state = MEI_DEV_DISABLED;
178 return 0; 178 return 0;
179 } 179 }
180 180
181 ret = mei_hw_start(dev); 181 ret = mei_hw_start(dev);
182 if (ret) { 182 if (ret) {
183 dev_err(dev->dev, "hw_start failed ret = %d\n", ret); 183 dev_err(dev->dev, "hw_start failed ret = %d\n", ret);
184 return ret; 184 return ret;
185 } 185 }
186 186
187 dev_dbg(dev->dev, "link is established start sending messages.\n"); 187 dev_dbg(dev->dev, "link is established start sending messages.\n");
188 188
189 dev->dev_state = MEI_DEV_INIT_CLIENTS; 189 dev->dev_state = MEI_DEV_INIT_CLIENTS;
190 ret = mei_hbm_start_req(dev); 190 ret = mei_hbm_start_req(dev);
191 if (ret) { 191 if (ret) {
192 dev_err(dev->dev, "hbm_start failed ret = %d\n", ret); 192 dev_err(dev->dev, "hbm_start failed ret = %d\n", ret);
193 dev->dev_state = MEI_DEV_RESETTING; 193 dev->dev_state = MEI_DEV_RESETTING;
194 return ret; 194 return ret;
195 } 195 }
196 196
197 return 0; 197 return 0;
198 } 198 }
199 EXPORT_SYMBOL_GPL(mei_reset); 199 EXPORT_SYMBOL_GPL(mei_reset);
200 200
201 /** 201 /**
202 * mei_start - initializes host and fw to start work. 202 * mei_start - initializes host and fw to start work.
203 * 203 *
204 * @dev: the device structure 204 * @dev: the device structure
205 * 205 *
206 * Return: 0 on success, <0 on failure. 206 * Return: 0 on success, <0 on failure.
207 */ 207 */
208 int mei_start(struct mei_device *dev) 208 int mei_start(struct mei_device *dev)
209 { 209 {
210 int ret; 210 int ret;
211 211
212 mutex_lock(&dev->device_lock); 212 mutex_lock(&dev->device_lock);
213 213
214 /* acknowledge interrupt and stop interrupts */ 214 /* acknowledge interrupt and stop interrupts */
215 mei_clear_interrupts(dev); 215 mei_clear_interrupts(dev);
216 216
217 mei_hw_config(dev); 217 mei_hw_config(dev);
218 218
219 dev_dbg(dev->dev, "reset in start the mei device.\n"); 219 dev_dbg(dev->dev, "reset in start the mei device.\n");
220 220
221 dev->reset_count = 0; 221 dev->reset_count = 0;
222 do { 222 do {
223 dev->dev_state = MEI_DEV_INITIALIZING; 223 dev->dev_state = MEI_DEV_INITIALIZING;
224 ret = mei_reset(dev); 224 ret = mei_reset(dev);
225 225
226 if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) { 226 if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
227 dev_err(dev->dev, "reset failed ret = %d", ret); 227 dev_err(dev->dev, "reset failed ret = %d", ret);
228 goto err; 228 goto err;
229 } 229 }
230 } while (ret); 230 } while (ret);
231 231
232 /* we cannot start the device w/o hbm start message completed */ 232 /* we cannot start the device w/o hbm start message completed */
233 if (dev->dev_state == MEI_DEV_DISABLED) { 233 if (dev->dev_state == MEI_DEV_DISABLED) {
234 dev_err(dev->dev, "reset failed"); 234 dev_err(dev->dev, "reset failed");
235 goto err; 235 goto err;
236 } 236 }
237 237
238 if (mei_hbm_start_wait(dev)) { 238 if (mei_hbm_start_wait(dev)) {
239 dev_err(dev->dev, "HBM haven't started"); 239 dev_err(dev->dev, "HBM haven't started");
240 goto err; 240 goto err;
241 } 241 }
242 242
243 if (!mei_host_is_ready(dev)) { 243 if (!mei_host_is_ready(dev)) {
244 dev_err(dev->dev, "host is not ready.\n"); 244 dev_err(dev->dev, "host is not ready.\n");
245 goto err; 245 goto err;
246 } 246 }
247 247
248 if (!mei_hw_is_ready(dev)) { 248 if (!mei_hw_is_ready(dev)) {
249 dev_err(dev->dev, "ME is not ready.\n"); 249 dev_err(dev->dev, "ME is not ready.\n");
250 goto err; 250 goto err;
251 } 251 }
252 252
253 if (!mei_hbm_version_is_supported(dev)) { 253 if (!mei_hbm_version_is_supported(dev)) {
254 dev_dbg(dev->dev, "MEI start failed.\n"); 254 dev_dbg(dev->dev, "MEI start failed.\n");
255 goto err; 255 goto err;
256 } 256 }
257 257
258 dev_dbg(dev->dev, "link layer has been established.\n"); 258 dev_dbg(dev->dev, "link layer has been established.\n");
259 259
260 mutex_unlock(&dev->device_lock); 260 mutex_unlock(&dev->device_lock);
261 return 0; 261 return 0;
262 err: 262 err:
263 dev_err(dev->dev, "link layer initialization failed.\n"); 263 dev_err(dev->dev, "link layer initialization failed.\n");
264 dev->dev_state = MEI_DEV_DISABLED; 264 dev->dev_state = MEI_DEV_DISABLED;
265 mutex_unlock(&dev->device_lock); 265 mutex_unlock(&dev->device_lock);
266 return -ENODEV; 266 return -ENODEV;
267 } 267 }
268 EXPORT_SYMBOL_GPL(mei_start); 268 EXPORT_SYMBOL_GPL(mei_start);
269 269
270 /** 270 /**
271 * mei_restart - restart device after suspend 271 * mei_restart - restart device after suspend
272 * 272 *
273 * @dev: the device structure 273 * @dev: the device structure
274 * 274 *
275 * Return: 0 on success or -ENODEV if the restart hasn't succeeded 275 * Return: 0 on success or -ENODEV if the restart hasn't succeeded
276 */ 276 */
277 int mei_restart(struct mei_device *dev) 277 int mei_restart(struct mei_device *dev)
278 { 278 {
279 int err; 279 int err;
280 280
281 mutex_lock(&dev->device_lock); 281 mutex_lock(&dev->device_lock);
282 282
283 mei_clear_interrupts(dev); 283 mei_clear_interrupts(dev);
284 284
285 dev->dev_state = MEI_DEV_POWER_UP; 285 dev->dev_state = MEI_DEV_POWER_UP;
286 dev->reset_count = 0; 286 dev->reset_count = 0;
287 287
288 err = mei_reset(dev); 288 err = mei_reset(dev);
289 289
290 mutex_unlock(&dev->device_lock); 290 mutex_unlock(&dev->device_lock);
291 291
292 if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) { 292 if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
293 dev_err(dev->dev, "device disabled = %d\n", err); 293 dev_err(dev->dev, "device disabled = %d\n", err);
294 return -ENODEV; 294 return -ENODEV;
295 } 295 }
296 296
297 /* try to start again */ 297 /* try to start again */
298 if (err) 298 if (err)
299 schedule_work(&dev->reset_work); 299 schedule_work(&dev->reset_work);
300 300
301 301
302 return 0; 302 return 0;
303 } 303 }
304 EXPORT_SYMBOL_GPL(mei_restart); 304 EXPORT_SYMBOL_GPL(mei_restart);
305 305
306 static void mei_reset_work(struct work_struct *work) 306 static void mei_reset_work(struct work_struct *work)
307 { 307 {
308 struct mei_device *dev = 308 struct mei_device *dev =
309 container_of(work, struct mei_device, reset_work); 309 container_of(work, struct mei_device, reset_work);
310 int ret; 310 int ret;
311 311
312 mutex_lock(&dev->device_lock); 312 mutex_lock(&dev->device_lock);
313 313
314 ret = mei_reset(dev); 314 ret = mei_reset(dev);
315 315
316 mutex_unlock(&dev->device_lock); 316 mutex_unlock(&dev->device_lock);
317 317
318 if (dev->dev_state == MEI_DEV_DISABLED) { 318 if (dev->dev_state == MEI_DEV_DISABLED) {
319 dev_err(dev->dev, "device disabled = %d\n", ret); 319 dev_err(dev->dev, "device disabled = %d\n", ret);
320 return; 320 return;
321 } 321 }
322 322
323 /* retry reset in case of failure */ 323 /* retry reset in case of failure */
324 if (ret) 324 if (ret)
325 schedule_work(&dev->reset_work); 325 schedule_work(&dev->reset_work);
326 } 326 }
327 327
328 void mei_stop(struct mei_device *dev) 328 void mei_stop(struct mei_device *dev)
329 { 329 {
330 dev_dbg(dev->dev, "stopping the device.\n"); 330 dev_dbg(dev->dev, "stopping the device.\n");
331 331
332 mei_cancel_work(dev); 332 mei_cancel_work(dev);
333 333
334 mei_nfc_host_exit(dev); 334 mei_nfc_host_exit(dev);
335 335
336 mei_cl_bus_remove_devices(dev); 336 mei_cl_bus_remove_devices(dev);
337 337
338 mutex_lock(&dev->device_lock); 338 mutex_lock(&dev->device_lock);
339 339
340 mei_wd_stop(dev); 340 mei_wd_stop(dev);
341 341
342 dev->dev_state = MEI_DEV_POWER_DOWN; 342 dev->dev_state = MEI_DEV_POWER_DOWN;
343 mei_reset(dev); 343 mei_reset(dev);
344 /* move device to disabled state unconditionally */
345 dev->dev_state = MEI_DEV_DISABLED;
344 346
345 mutex_unlock(&dev->device_lock); 347 mutex_unlock(&dev->device_lock);
346 348
347 mei_watchdog_unregister(dev); 349 mei_watchdog_unregister(dev);
348 } 350 }
349 EXPORT_SYMBOL_GPL(mei_stop); 351 EXPORT_SYMBOL_GPL(mei_stop);
350 352
351 /** 353 /**
352 * mei_write_is_idle - check if the write queues are idle 354 * mei_write_is_idle - check if the write queues are idle
353 * 355 *
354 * @dev: the device structure 356 * @dev: the device structure
355 * 357 *
356 * Return: true of there is no pending write 358 * Return: true of there is no pending write
357 */ 359 */
358 bool mei_write_is_idle(struct mei_device *dev) 360 bool mei_write_is_idle(struct mei_device *dev)
359 { 361 {
360 bool idle = (dev->dev_state == MEI_DEV_ENABLED && 362 bool idle = (dev->dev_state == MEI_DEV_ENABLED &&
361 list_empty(&dev->ctrl_wr_list.list) && 363 list_empty(&dev->ctrl_wr_list.list) &&
362 list_empty(&dev->write_list.list)); 364 list_empty(&dev->write_list.list));
363 365
364 dev_dbg(dev->dev, "write pg: is idle[%d] state=%s ctrl=%d write=%d\n", 366 dev_dbg(dev->dev, "write pg: is idle[%d] state=%s ctrl=%d write=%d\n",
365 idle, 367 idle,
366 mei_dev_state_str(dev->dev_state), 368 mei_dev_state_str(dev->dev_state),
367 list_empty(&dev->ctrl_wr_list.list), 369 list_empty(&dev->ctrl_wr_list.list),
368 list_empty(&dev->write_list.list)); 370 list_empty(&dev->write_list.list));
369 371
370 return idle; 372 return idle;
371 } 373 }
372 EXPORT_SYMBOL_GPL(mei_write_is_idle); 374 EXPORT_SYMBOL_GPL(mei_write_is_idle);
373 375
374 /** 376 /**
375 * mei_device_init -- initialize mei_device structure 377 * mei_device_init -- initialize mei_device structure
376 * 378 *
377 * @dev: the mei device 379 * @dev: the mei device
378 * @device: the device structure 380 * @device: the device structure
379 * @hw_ops: hw operations 381 * @hw_ops: hw operations
380 */ 382 */
381 void mei_device_init(struct mei_device *dev, 383 void mei_device_init(struct mei_device *dev,
382 struct device *device, 384 struct device *device,
383 const struct mei_hw_ops *hw_ops) 385 const struct mei_hw_ops *hw_ops)
384 { 386 {
385 /* setup our list array */ 387 /* setup our list array */
386 INIT_LIST_HEAD(&dev->file_list); 388 INIT_LIST_HEAD(&dev->file_list);
387 INIT_LIST_HEAD(&dev->device_list); 389 INIT_LIST_HEAD(&dev->device_list);
388 INIT_LIST_HEAD(&dev->me_clients); 390 INIT_LIST_HEAD(&dev->me_clients);
389 mutex_init(&dev->device_lock); 391 mutex_init(&dev->device_lock);
390 init_waitqueue_head(&dev->wait_hw_ready); 392 init_waitqueue_head(&dev->wait_hw_ready);
391 init_waitqueue_head(&dev->wait_pg); 393 init_waitqueue_head(&dev->wait_pg);
392 init_waitqueue_head(&dev->wait_hbm_start); 394 init_waitqueue_head(&dev->wait_hbm_start);
393 init_waitqueue_head(&dev->wait_stop_wd); 395 init_waitqueue_head(&dev->wait_stop_wd);
394 dev->dev_state = MEI_DEV_INITIALIZING; 396 dev->dev_state = MEI_DEV_INITIALIZING;
395 dev->reset_count = 0; 397 dev->reset_count = 0;
396 398
397 mei_io_list_init(&dev->read_list); 399 mei_io_list_init(&dev->read_list);
398 mei_io_list_init(&dev->write_list); 400 mei_io_list_init(&dev->write_list);
399 mei_io_list_init(&dev->write_waiting_list); 401 mei_io_list_init(&dev->write_waiting_list);
400 mei_io_list_init(&dev->ctrl_wr_list); 402 mei_io_list_init(&dev->ctrl_wr_list);
401 mei_io_list_init(&dev->ctrl_rd_list); 403 mei_io_list_init(&dev->ctrl_rd_list);
402 404
403 INIT_DELAYED_WORK(&dev->timer_work, mei_timer); 405 INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
404 INIT_WORK(&dev->init_work, mei_host_client_init); 406 INIT_WORK(&dev->init_work, mei_host_client_init);
405 INIT_WORK(&dev->reset_work, mei_reset_work); 407 INIT_WORK(&dev->reset_work, mei_reset_work);
406 408
407 INIT_LIST_HEAD(&dev->wd_cl.link); 409 INIT_LIST_HEAD(&dev->wd_cl.link);
408 INIT_LIST_HEAD(&dev->iamthif_cl.link); 410 INIT_LIST_HEAD(&dev->iamthif_cl.link);
409 mei_io_list_init(&dev->amthif_cmd_list); 411 mei_io_list_init(&dev->amthif_cmd_list);
410 mei_io_list_init(&dev->amthif_rd_complete_list); 412 mei_io_list_init(&dev->amthif_rd_complete_list);
411 413
412 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); 414 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
413 dev->open_handle_count = 0; 415 dev->open_handle_count = 0;
414 416
415 /* 417 /*
416 * Reserving the first client ID 418 * Reserving the first client ID
417 * 0: Reserved for MEI Bus Message communications 419 * 0: Reserved for MEI Bus Message communications
418 */ 420 */
419 bitmap_set(dev->host_clients_map, 0, 1); 421 bitmap_set(dev->host_clients_map, 0, 1);
420 422
421 dev->pg_event = MEI_PG_EVENT_IDLE; 423 dev->pg_event = MEI_PG_EVENT_IDLE;
422 dev->ops = hw_ops; 424 dev->ops = hw_ops;
423 dev->dev = device; 425 dev->dev = device;
424 } 426 }
425 EXPORT_SYMBOL_GPL(mei_device_init); 427 EXPORT_SYMBOL_GPL(mei_device_init);
426 428
427 429