Commit | Line | Data |
---|---|---|
3ce72726 OW |
1 | /* |
2 | * | |
3 | * Intel Management Engine Interface (Intel MEI) Linux driver | |
733ba91c | 4 | * Copyright (c) 2003-2012, Intel Corporation. |
3ce72726 OW |
5 | * |
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. | |
9 | * | |
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 | |
13 | * more details. | |
14 | * | |
15 | */ | |
16 | ||
17 | #include <linux/pci.h> | |
06ecd645 TW |
18 | |
19 | #include <linux/kthread.h> | |
20 | #include <linux/interrupt.h> | |
47a73801 TW |
21 | |
22 | #include "mei_dev.h" | |
9dc64d6a | 23 | #include "hw-me.h" |
3ce72726 | 24 | |
06ecd645 TW |
25 | #include "hbm.h" |
26 | ||
27 | ||
3a65dd4e | 28 | /** |
b68301e9 | 29 | * mei_me_reg_read - Reads 32bit data from the mei device |
3a65dd4e TW |
30 | * |
31 | * @dev: the device structure | |
32 | * @offset: offset from which to read the data | |
33 | * | |
34 | * returns register value (u32) | |
35 | */ | |
b68301e9 | 36 | static inline u32 mei_me_reg_read(const struct mei_me_hw *hw, |
3a65dd4e TW |
37 | unsigned long offset) |
38 | { | |
52c34561 | 39 | return ioread32(hw->mem_addr + offset); |
3a65dd4e TW |
40 | } |
41 | ||
42 | ||
43 | /** | |
b68301e9 | 44 | * mei_me_reg_write - Writes 32bit data to the mei device |
3a65dd4e TW |
45 | * |
46 | * @dev: the device structure | |
47 | * @offset: offset from which to write the data | |
48 | * @value: register value to write (u32) | |
49 | */ | |
b68301e9 | 50 | static inline void mei_me_reg_write(const struct mei_me_hw *hw, |
3a65dd4e TW |
51 | unsigned long offset, u32 value) |
52 | { | |
52c34561 | 53 | iowrite32(value, hw->mem_addr + offset); |
3a65dd4e | 54 | } |
3ce72726 | 55 | |
3a65dd4e | 56 | /** |
b68301e9 | 57 | * mei_me_mecbrw_read - Reads 32bit data from ME circular buffer |
d025284d | 58 | * read window register |
3a65dd4e TW |
59 | * |
60 | * @dev: the device structure | |
61 | * | |
d025284d | 62 | * returns ME_CB_RW register value (u32) |
3a65dd4e | 63 | */ |
827eef51 | 64 | static u32 mei_me_mecbrw_read(const struct mei_device *dev) |
3a65dd4e | 65 | { |
b68301e9 | 66 | return mei_me_reg_read(to_me_hw(dev), ME_CB_RW); |
3a65dd4e TW |
67 | } |
68 | /** | |
b68301e9 | 69 | * mei_me_mecsr_read - Reads 32bit data from the ME CSR |
3a65dd4e TW |
70 | * |
71 | * @dev: the device structure | |
72 | * | |
73 | * returns ME_CSR_HA register value (u32) | |
74 | */ | |
b68301e9 | 75 | static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw) |
3a65dd4e | 76 | { |
b68301e9 | 77 | return mei_me_reg_read(hw, ME_CSR_HA); |
3a65dd4e | 78 | } |
3ce72726 OW |
79 | |
80 | /** | |
d025284d TW |
81 | * mei_hcsr_read - Reads 32bit data from the host CSR |
82 | * | |
83 | * @dev: the device structure | |
84 | * | |
85 | * returns H_CSR register value (u32) | |
86 | */ | |
52c34561 | 87 | static inline u32 mei_hcsr_read(const struct mei_me_hw *hw) |
d025284d | 88 | { |
b68301e9 | 89 | return mei_me_reg_read(hw, H_CSR); |
d025284d TW |
90 | } |
91 | ||
92 | /** | |
93 | * mei_hcsr_set - writes H_CSR register to the mei device, | |
3ce72726 OW |
94 | * and ignores the H_IS bit for it is write-one-to-zero. |
95 | * | |
96 | * @dev: the device structure | |
97 | */ | |
52c34561 | 98 | static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr) |
3ce72726 | 99 | { |
88eb99f2 | 100 | hcsr &= ~H_IS; |
b68301e9 | 101 | mei_me_reg_write(hw, H_CSR, hcsr); |
3ce72726 OW |
102 | } |
103 | ||
e7e0c231 TW |
104 | |
105 | /** | |
393b148f | 106 | * mei_me_hw_config - configure hw dependent settings |
e7e0c231 TW |
107 | * |
108 | * @dev: mei device | |
109 | */ | |
827eef51 | 110 | static void mei_me_hw_config(struct mei_device *dev) |
e7e0c231 | 111 | { |
52c34561 | 112 | u32 hcsr = mei_hcsr_read(to_me_hw(dev)); |
e7e0c231 TW |
113 | /* Doesn't change in runtime */ |
114 | dev->hbuf_depth = (hcsr & H_CBD) >> 24; | |
115 | } | |
3ce72726 | 116 | /** |
d025284d | 117 | * mei_clear_interrupts - clear and stop interrupts |
3a65dd4e TW |
118 | * |
119 | * @dev: the device structure | |
120 | */ | |
827eef51 | 121 | static void mei_me_intr_clear(struct mei_device *dev) |
3a65dd4e | 122 | { |
52c34561 TW |
123 | struct mei_me_hw *hw = to_me_hw(dev); |
124 | u32 hcsr = mei_hcsr_read(hw); | |
9ea73ddd | 125 | if ((hcsr & H_IS) == H_IS) |
b68301e9 | 126 | mei_me_reg_write(hw, H_CSR, hcsr); |
3a65dd4e | 127 | } |
3a65dd4e | 128 | /** |
827eef51 | 129 | * mei_me_intr_enable - enables mei device interrupts |
3ce72726 OW |
130 | * |
131 | * @dev: the device structure | |
132 | */ | |
827eef51 | 133 | static void mei_me_intr_enable(struct mei_device *dev) |
3ce72726 | 134 | { |
52c34561 TW |
135 | struct mei_me_hw *hw = to_me_hw(dev); |
136 | u32 hcsr = mei_hcsr_read(hw); | |
9ea73ddd | 137 | hcsr |= H_IE; |
52c34561 | 138 | mei_hcsr_set(hw, hcsr); |
3ce72726 OW |
139 | } |
140 | ||
141 | /** | |
3a65dd4e | 142 | * mei_disable_interrupts - disables mei device interrupts |
3ce72726 OW |
143 | * |
144 | * @dev: the device structure | |
145 | */ | |
827eef51 | 146 | static void mei_me_intr_disable(struct mei_device *dev) |
3ce72726 | 147 | { |
52c34561 TW |
148 | struct mei_me_hw *hw = to_me_hw(dev); |
149 | u32 hcsr = mei_hcsr_read(hw); | |
9ea73ddd | 150 | hcsr &= ~H_IE; |
52c34561 | 151 | mei_hcsr_set(hw, hcsr); |
3ce72726 OW |
152 | } |
153 | ||
68f8ea18 TW |
154 | /** |
155 | * mei_me_hw_reset_release - release device from the reset | |
156 | * | |
157 | * @dev: the device structure | |
158 | */ | |
159 | static void mei_me_hw_reset_release(struct mei_device *dev) | |
160 | { | |
161 | struct mei_me_hw *hw = to_me_hw(dev); | |
162 | u32 hcsr = mei_hcsr_read(hw); | |
163 | ||
164 | hcsr |= H_IG; | |
165 | hcsr &= ~H_RST; | |
166 | mei_hcsr_set(hw, hcsr); | |
167 | } | |
adfba322 | 168 | /** |
827eef51 | 169 | * mei_me_hw_reset - resets fw via mei csr register. |
adfba322 TW |
170 | * |
171 | * @dev: the device structure | |
393b148f | 172 | * @intr_enable: if interrupt should be enabled after reset. |
adfba322 | 173 | */ |
c20c68d5 | 174 | static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) |
adfba322 | 175 | { |
52c34561 TW |
176 | struct mei_me_hw *hw = to_me_hw(dev); |
177 | u32 hcsr = mei_hcsr_read(hw); | |
adfba322 | 178 | |
ff96066e | 179 | hcsr |= H_RST | H_IG | H_IS; |
adfba322 TW |
180 | |
181 | if (intr_enable) | |
182 | hcsr |= H_IE; | |
183 | else | |
ff96066e | 184 | hcsr &= ~H_IE; |
adfba322 | 185 | |
ff96066e | 186 | mei_me_reg_write(hw, H_CSR, hcsr); |
adfba322 | 187 | |
68f8ea18 TW |
188 | if (dev->dev_state == MEI_DEV_POWER_DOWN) |
189 | mei_me_hw_reset_release(dev); | |
adfba322 | 190 | |
c20c68d5 | 191 | return 0; |
adfba322 TW |
192 | } |
193 | ||
115ba28c | 194 | /** |
827eef51 | 195 | * mei_me_host_set_ready - enable device |
115ba28c TW |
196 | * |
197 | * @dev - mei device | |
198 | * returns bool | |
199 | */ | |
200 | ||
827eef51 | 201 | static void mei_me_host_set_ready(struct mei_device *dev) |
115ba28c | 202 | { |
52c34561 TW |
203 | struct mei_me_hw *hw = to_me_hw(dev); |
204 | hw->host_hw_state |= H_IE | H_IG | H_RDY; | |
205 | mei_hcsr_set(hw, hw->host_hw_state); | |
115ba28c TW |
206 | } |
207 | /** | |
827eef51 | 208 | * mei_me_host_is_ready - check whether the host has turned ready |
115ba28c TW |
209 | * |
210 | * @dev - mei device | |
211 | * returns bool | |
212 | */ | |
827eef51 | 213 | static bool mei_me_host_is_ready(struct mei_device *dev) |
115ba28c | 214 | { |
52c34561 TW |
215 | struct mei_me_hw *hw = to_me_hw(dev); |
216 | hw->host_hw_state = mei_hcsr_read(hw); | |
217 | return (hw->host_hw_state & H_RDY) == H_RDY; | |
115ba28c TW |
218 | } |
219 | ||
220 | /** | |
827eef51 | 221 | * mei_me_hw_is_ready - check whether the me(hw) has turned ready |
115ba28c TW |
222 | * |
223 | * @dev - mei device | |
224 | * returns bool | |
225 | */ | |
827eef51 | 226 | static bool mei_me_hw_is_ready(struct mei_device *dev) |
115ba28c | 227 | { |
52c34561 | 228 | struct mei_me_hw *hw = to_me_hw(dev); |
b68301e9 | 229 | hw->me_hw_state = mei_me_mecsr_read(hw); |
52c34561 | 230 | return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; |
115ba28c | 231 | } |
3a65dd4e | 232 | |
aafae7ec TW |
233 | static int mei_me_hw_ready_wait(struct mei_device *dev) |
234 | { | |
235 | int err; | |
236 | if (mei_me_hw_is_ready(dev)) | |
237 | return 0; | |
238 | ||
dab9bf41 | 239 | dev->recvd_hw_ready = false; |
aafae7ec TW |
240 | mutex_unlock(&dev->device_lock); |
241 | err = wait_event_interruptible_timeout(dev->wait_hw_ready, | |
dab9bf41 TW |
242 | dev->recvd_hw_ready, |
243 | mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); | |
aafae7ec TW |
244 | mutex_lock(&dev->device_lock); |
245 | if (!err && !dev->recvd_hw_ready) { | |
dab9bf41 TW |
246 | if (!err) |
247 | err = -ETIMEDOUT; | |
aafae7ec | 248 | dev_err(&dev->pdev->dev, |
dab9bf41 TW |
249 | "wait hw ready failed. status = %d\n", err); |
250 | return err; | |
aafae7ec TW |
251 | } |
252 | ||
253 | dev->recvd_hw_ready = false; | |
254 | return 0; | |
255 | } | |
256 | ||
257 | static int mei_me_hw_start(struct mei_device *dev) | |
258 | { | |
259 | int ret = mei_me_hw_ready_wait(dev); | |
260 | if (ret) | |
261 | return ret; | |
262 | dev_dbg(&dev->pdev->dev, "hw is ready\n"); | |
263 | ||
264 | mei_me_host_set_ready(dev); | |
265 | return ret; | |
266 | } | |
267 | ||
268 | ||
3ce72726 | 269 | /** |
726917f0 | 270 | * mei_hbuf_filled_slots - gets number of device filled buffer slots |
3ce72726 | 271 | * |
7353f85c | 272 | * @dev: the device structure |
3ce72726 OW |
273 | * |
274 | * returns number of filled slots | |
275 | */ | |
726917f0 | 276 | static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) |
3ce72726 | 277 | { |
52c34561 | 278 | struct mei_me_hw *hw = to_me_hw(dev); |
3ce72726 OW |
279 | char read_ptr, write_ptr; |
280 | ||
52c34561 | 281 | hw->host_hw_state = mei_hcsr_read(hw); |
726917f0 | 282 | |
52c34561 TW |
283 | read_ptr = (char) ((hw->host_hw_state & H_CBRP) >> 8); |
284 | write_ptr = (char) ((hw->host_hw_state & H_CBWP) >> 16); | |
3ce72726 OW |
285 | |
286 | return (unsigned char) (write_ptr - read_ptr); | |
287 | } | |
288 | ||
289 | /** | |
393b148f | 290 | * mei_me_hbuf_is_empty - checks if host buffer is empty. |
3ce72726 OW |
291 | * |
292 | * @dev: the device structure | |
293 | * | |
726917f0 | 294 | * returns true if empty, false - otherwise. |
3ce72726 | 295 | */ |
827eef51 | 296 | static bool mei_me_hbuf_is_empty(struct mei_device *dev) |
3ce72726 | 297 | { |
726917f0 | 298 | return mei_hbuf_filled_slots(dev) == 0; |
3ce72726 OW |
299 | } |
300 | ||
301 | /** | |
827eef51 | 302 | * mei_me_hbuf_empty_slots - counts write empty slots. |
3ce72726 OW |
303 | * |
304 | * @dev: the device structure | |
305 | * | |
306 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count | |
307 | */ | |
827eef51 | 308 | static int mei_me_hbuf_empty_slots(struct mei_device *dev) |
3ce72726 | 309 | { |
24aadc80 | 310 | unsigned char filled_slots, empty_slots; |
3ce72726 | 311 | |
726917f0 | 312 | filled_slots = mei_hbuf_filled_slots(dev); |
24aadc80 | 313 | empty_slots = dev->hbuf_depth - filled_slots; |
3ce72726 OW |
314 | |
315 | /* check for overflow */ | |
24aadc80 | 316 | if (filled_slots > dev->hbuf_depth) |
3ce72726 OW |
317 | return -EOVERFLOW; |
318 | ||
319 | return empty_slots; | |
320 | } | |
321 | ||
827eef51 TW |
322 | static size_t mei_me_hbuf_max_len(const struct mei_device *dev) |
323 | { | |
324 | return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); | |
325 | } | |
326 | ||
327 | ||
3ce72726 OW |
328 | /** |
329 | * mei_write_message - writes a message to mei device. | |
330 | * | |
331 | * @dev: the device structure | |
7353f85c | 332 | * @header: mei HECI header of message |
438763f3 | 333 | * @buf: message payload will be written |
3ce72726 | 334 | * |
1ccb7b62 | 335 | * This function returns -EIO if write has failed |
3ce72726 | 336 | */ |
827eef51 TW |
337 | static int mei_me_write_message(struct mei_device *dev, |
338 | struct mei_msg_hdr *header, | |
339 | unsigned char *buf) | |
3ce72726 | 340 | { |
52c34561 | 341 | struct mei_me_hw *hw = to_me_hw(dev); |
c8c8d080 | 342 | unsigned long rem; |
438763f3 | 343 | unsigned long length = header->length; |
169d1338 | 344 | u32 *reg_buf = (u32 *)buf; |
88eb99f2 | 345 | u32 hcsr; |
c8c8d080 | 346 | u32 dw_cnt; |
169d1338 TW |
347 | int i; |
348 | int empty_slots; | |
3ce72726 | 349 | |
15d4acc5 | 350 | dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header)); |
3ce72726 | 351 | |
726917f0 | 352 | empty_slots = mei_hbuf_empty_slots(dev); |
169d1338 | 353 | dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); |
3ce72726 | 354 | |
7bdf72d3 | 355 | dw_cnt = mei_data2slots(length); |
169d1338 | 356 | if (empty_slots < 0 || dw_cnt > empty_slots) |
1ccb7b62 | 357 | return -EIO; |
3ce72726 | 358 | |
b68301e9 | 359 | mei_me_reg_write(hw, H_CB_WW, *((u32 *) header)); |
3ce72726 | 360 | |
169d1338 | 361 | for (i = 0; i < length / 4; i++) |
b68301e9 | 362 | mei_me_reg_write(hw, H_CB_WW, reg_buf[i]); |
3ce72726 | 363 | |
169d1338 TW |
364 | rem = length & 0x3; |
365 | if (rem > 0) { | |
366 | u32 reg = 0; | |
367 | memcpy(®, &buf[length - rem], rem); | |
b68301e9 | 368 | mei_me_reg_write(hw, H_CB_WW, reg); |
3ce72726 OW |
369 | } |
370 | ||
52c34561 TW |
371 | hcsr = mei_hcsr_read(hw) | H_IG; |
372 | mei_hcsr_set(hw, hcsr); | |
827eef51 | 373 | if (!mei_me_hw_is_ready(dev)) |
1ccb7b62 | 374 | return -EIO; |
3ce72726 | 375 | |
1ccb7b62 | 376 | return 0; |
3ce72726 OW |
377 | } |
378 | ||
379 | /** | |
827eef51 | 380 | * mei_me_count_full_read_slots - counts read full slots. |
3ce72726 OW |
381 | * |
382 | * @dev: the device structure | |
383 | * | |
384 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count | |
385 | */ | |
827eef51 | 386 | static int mei_me_count_full_read_slots(struct mei_device *dev) |
3ce72726 | 387 | { |
52c34561 | 388 | struct mei_me_hw *hw = to_me_hw(dev); |
3ce72726 OW |
389 | char read_ptr, write_ptr; |
390 | unsigned char buffer_depth, filled_slots; | |
391 | ||
b68301e9 | 392 | hw->me_hw_state = mei_me_mecsr_read(hw); |
52c34561 TW |
393 | buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24); |
394 | read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8); | |
395 | write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16); | |
3ce72726 OW |
396 | filled_slots = (unsigned char) (write_ptr - read_ptr); |
397 | ||
398 | /* check for overflow */ | |
399 | if (filled_slots > buffer_depth) | |
400 | return -EOVERFLOW; | |
401 | ||
402 | dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots); | |
403 | return (int)filled_slots; | |
404 | } | |
405 | ||
406 | /** | |
827eef51 | 407 | * mei_me_read_slots - reads a message from mei device. |
3ce72726 OW |
408 | * |
409 | * @dev: the device structure | |
410 | * @buffer: message buffer will be written | |
411 | * @buffer_length: message size will be read | |
412 | */ | |
827eef51 | 413 | static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer, |
edf1eed4 | 414 | unsigned long buffer_length) |
3ce72726 | 415 | { |
52c34561 | 416 | struct mei_me_hw *hw = to_me_hw(dev); |
edf1eed4 | 417 | u32 *reg_buf = (u32 *)buffer; |
88eb99f2 | 418 | u32 hcsr; |
3ce72726 | 419 | |
edf1eed4 | 420 | for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) |
827eef51 | 421 | *reg_buf++ = mei_me_mecbrw_read(dev); |
3ce72726 OW |
422 | |
423 | if (buffer_length > 0) { | |
827eef51 | 424 | u32 reg = mei_me_mecbrw_read(dev); |
edf1eed4 | 425 | memcpy(reg_buf, ®, buffer_length); |
3ce72726 OW |
426 | } |
427 | ||
52c34561 TW |
428 | hcsr = mei_hcsr_read(hw) | H_IG; |
429 | mei_hcsr_set(hw, hcsr); | |
827eef51 | 430 | return 0; |
3ce72726 OW |
431 | } |
432 | ||
06ecd645 TW |
433 | /** |
434 | * mei_me_irq_quick_handler - The ISR of the MEI device | |
435 | * | |
436 | * @irq: The irq number | |
437 | * @dev_id: pointer to the device structure | |
438 | * | |
439 | * returns irqreturn_t | |
440 | */ | |
441 | ||
442 | irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id) | |
443 | { | |
444 | struct mei_device *dev = (struct mei_device *) dev_id; | |
445 | struct mei_me_hw *hw = to_me_hw(dev); | |
446 | u32 csr_reg = mei_hcsr_read(hw); | |
447 | ||
448 | if ((csr_reg & H_IS) != H_IS) | |
449 | return IRQ_NONE; | |
450 | ||
451 | /* clear H_IS bit in H_CSR */ | |
b68301e9 | 452 | mei_me_reg_write(hw, H_CSR, csr_reg); |
06ecd645 TW |
453 | |
454 | return IRQ_WAKE_THREAD; | |
455 | } | |
456 | ||
457 | /** | |
458 | * mei_me_irq_thread_handler - function called after ISR to handle the interrupt | |
459 | * processing. | |
460 | * | |
461 | * @irq: The irq number | |
462 | * @dev_id: pointer to the device structure | |
463 | * | |
464 | * returns irqreturn_t | |
465 | * | |
466 | */ | |
467 | irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |
468 | { | |
469 | struct mei_device *dev = (struct mei_device *) dev_id; | |
470 | struct mei_cl_cb complete_list; | |
06ecd645 TW |
471 | s32 slots; |
472 | int rets; | |
06ecd645 TW |
473 | |
474 | dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); | |
475 | /* initialize our complete list */ | |
476 | mutex_lock(&dev->device_lock); | |
477 | mei_io_list_init(&complete_list); | |
478 | ||
479 | /* Ack the interrupt here | |
480 | * In case of MSI we don't go through the quick handler */ | |
481 | if (pci_dev_msi_enabled(dev->pdev)) | |
482 | mei_clear_interrupts(dev); | |
483 | ||
484 | /* check if ME wants a reset */ | |
485 | if (!mei_hw_is_ready(dev) && | |
0cfee51c | 486 | dev->dev_state != MEI_DEV_RESETTING && |
315a383a TW |
487 | dev->dev_state != MEI_DEV_INITIALIZING && |
488 | dev->dev_state != MEI_DEV_POWER_DOWN && | |
489 | dev->dev_state != MEI_DEV_POWER_UP) { | |
06ecd645 TW |
490 | dev_dbg(&dev->pdev->dev, "FW not ready.\n"); |
491 | mei_reset(dev, 1); | |
492 | mutex_unlock(&dev->device_lock); | |
493 | return IRQ_HANDLED; | |
494 | } | |
495 | ||
496 | /* check if we need to start the dev */ | |
497 | if (!mei_host_is_ready(dev)) { | |
498 | if (mei_hw_is_ready(dev)) { | |
499 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); | |
500 | ||
aafae7ec TW |
501 | dev->recvd_hw_ready = true; |
502 | wake_up_interruptible(&dev->wait_hw_ready); | |
06ecd645 | 503 | |
06ecd645 TW |
504 | mutex_unlock(&dev->device_lock); |
505 | return IRQ_HANDLED; | |
506 | } else { | |
68f8ea18 TW |
507 | dev_dbg(&dev->pdev->dev, "Reset Completed.\n"); |
508 | mei_me_hw_reset_release(dev); | |
06ecd645 TW |
509 | mutex_unlock(&dev->device_lock); |
510 | return IRQ_HANDLED; | |
511 | } | |
512 | } | |
513 | /* check slots available for reading */ | |
514 | slots = mei_count_full_read_slots(dev); | |
515 | while (slots > 0) { | |
516 | /* we have urgent data to send so break the read */ | |
517 | if (dev->wr_ext_msg.hdr.length) | |
518 | break; | |
519 | dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots); | |
520 | dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n"); | |
521 | rets = mei_irq_read_handler(dev, &complete_list, &slots); | |
522 | if (rets) | |
523 | goto end; | |
524 | } | |
525 | rets = mei_irq_write_handler(dev, &complete_list); | |
526 | end: | |
527 | dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); | |
330dd7da | 528 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); |
06ecd645 | 529 | |
06ecd645 | 530 | mutex_unlock(&dev->device_lock); |
06ecd645 | 531 | |
4c6e22b8 | 532 | mei_irq_compl_handler(dev, &complete_list); |
06ecd645 | 533 | |
06ecd645 TW |
534 | return IRQ_HANDLED; |
535 | } | |
827eef51 TW |
536 | static const struct mei_hw_ops mei_me_hw_ops = { |
537 | ||
827eef51 TW |
538 | .host_is_ready = mei_me_host_is_ready, |
539 | ||
540 | .hw_is_ready = mei_me_hw_is_ready, | |
541 | .hw_reset = mei_me_hw_reset, | |
aafae7ec TW |
542 | .hw_config = mei_me_hw_config, |
543 | .hw_start = mei_me_hw_start, | |
827eef51 TW |
544 | |
545 | .intr_clear = mei_me_intr_clear, | |
546 | .intr_enable = mei_me_intr_enable, | |
547 | .intr_disable = mei_me_intr_disable, | |
548 | ||
549 | .hbuf_free_slots = mei_me_hbuf_empty_slots, | |
550 | .hbuf_is_ready = mei_me_hbuf_is_empty, | |
551 | .hbuf_max_len = mei_me_hbuf_max_len, | |
552 | ||
553 | .write = mei_me_write_message, | |
554 | ||
555 | .rdbuf_full_slots = mei_me_count_full_read_slots, | |
556 | .read_hdr = mei_me_mecbrw_read, | |
557 | .read = mei_me_read_slots | |
558 | }; | |
559 | ||
52c34561 | 560 | /** |
393b148f | 561 | * mei_me_dev_init - allocates and initializes the mei device structure |
52c34561 TW |
562 | * |
563 | * @pdev: The pci device structure | |
564 | * | |
565 | * returns The mei_device_device pointer on success, NULL on failure. | |
566 | */ | |
567 | struct mei_device *mei_me_dev_init(struct pci_dev *pdev) | |
568 | { | |
569 | struct mei_device *dev; | |
570 | ||
571 | dev = kzalloc(sizeof(struct mei_device) + | |
572 | sizeof(struct mei_me_hw), GFP_KERNEL); | |
573 | if (!dev) | |
574 | return NULL; | |
575 | ||
576 | mei_device_init(dev); | |
577 | ||
827eef51 TW |
578 | dev->ops = &mei_me_hw_ops; |
579 | ||
52c34561 TW |
580 | dev->pdev = pdev; |
581 | return dev; | |
582 | } | |
06ecd645 | 583 |