]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/misc/mei/interrupt.c
VMCI: Some header and config files.
[mirror_ubuntu-zesty-kernel.git] / drivers / misc / mei / interrupt.c
CommitLineData
fb7d879f
OW
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
733ba91c 4 * Copyright (c) 2003-2012, Intel Corporation.
fb7d879f
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
18#include <linux/pci.h>
19#include <linux/kthread.h>
20#include <linux/interrupt.h>
21#include <linux/fs.h>
22#include <linux/jiffies.h>
23
4f3afe1d 24#include <linux/mei.h>
47a73801
TW
25
26#include "mei_dev.h"
fb7d879f
OW
27#include "interface.h"
28
29
fb7d879f
OW
30/**
31 * _mei_cmpl - processes completed operation.
32 *
33 * @cl: private data of the file object.
34 * @cb_pos: callback block.
35 */
36static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
37{
4b8960b4 38 if (cb_pos->fop_type == MEI_FOP_WRITE) {
601a1efa 39 mei_io_cb_free(cb_pos);
fb7d879f
OW
40 cb_pos = NULL;
41 cl->writing_state = MEI_WRITE_COMPLETE;
42 if (waitqueue_active(&cl->tx_wait))
43 wake_up_interruptible(&cl->tx_wait);
44
4b8960b4 45 } else if (cb_pos->fop_type == MEI_FOP_READ &&
fb7d879f
OW
46 MEI_READING == cl->reading_state) {
47 cl->reading_state = MEI_READ_COMPLETE;
48 if (waitqueue_active(&cl->rx_wait))
49 wake_up_interruptible(&cl->rx_wait);
50
51 }
52}
53
fb7d879f
OW
54/**
55 * _mei_irq_thread_state_ok - checks if mei header matches file private data
56 *
57 * @cl: private data of the file object
58 * @mei_hdr: header of mei client message
59 *
60 * returns !=0 if matches, 0 if no match.
61 */
62static int _mei_irq_thread_state_ok(struct mei_cl *cl,
63 struct mei_msg_hdr *mei_hdr)
64{
65 return (cl->host_client_id == mei_hdr->host_addr &&
66 cl->me_client_id == mei_hdr->me_addr &&
67 cl->state == MEI_FILE_CONNECTED &&
68 MEI_READ_COMPLETE != cl->reading_state);
69}
70
71/**
72 * mei_irq_thread_read_client_message - bottom half read routine after ISR to
73 * handle the read mei client message data processing.
74 *
75 * @complete_list: An instance of our list structure
76 * @dev: the device structure
77 * @mei_hdr: header of mei client message
78 *
79 * returns 0 on success, <0 on failure.
80 */
fb601adb 81static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list,
fb7d879f
OW
82 struct mei_device *dev,
83 struct mei_msg_hdr *mei_hdr)
84{
85 struct mei_cl *cl;
86 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
479bc59d 87 unsigned char *buffer = NULL;
fb7d879f
OW
88
89 dev_dbg(&dev->pdev->dev, "start client msg\n");
fb601adb 90 if (list_empty(&dev->read_list.list))
fb7d879f
OW
91 goto quit;
92
fb601adb 93 list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) {
db3ed431 94 cl = cb_pos->cl;
fb7d879f
OW
95 if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
96 cl->reading_state = MEI_READING;
ebb108ef 97 buffer = cb_pos->response_buffer.data + cb_pos->buf_idx;
fb7d879f
OW
98
99 if (cb_pos->response_buffer.size <
ebb108ef 100 mei_hdr->length + cb_pos->buf_idx) {
fb7d879f 101 dev_dbg(&dev->pdev->dev, "message overflow.\n");
fb601adb 102 list_del(&cb_pos->list);
fb7d879f
OW
103 return -ENOMEM;
104 }
105 if (buffer)
106 mei_read_slots(dev, buffer, mei_hdr->length);
107
ebb108ef 108 cb_pos->buf_idx += mei_hdr->length;
fb7d879f
OW
109 if (mei_hdr->msg_complete) {
110 cl->status = 0;
fb601adb 111 list_del(&cb_pos->list);
fb7d879f 112 dev_dbg(&dev->pdev->dev,
a4136b49 113 "completed read H cl = %d, ME cl = %d, length = %lu\n",
fb7d879f
OW
114 cl->host_client_id,
115 cl->me_client_id,
ebb108ef
TW
116 cb_pos->buf_idx);
117
fb601adb
TW
118 list_add_tail(&cb_pos->list,
119 &complete_list->list);
fb7d879f
OW
120 }
121
122 break;
123 }
124
125 }
126
127quit:
128 dev_dbg(&dev->pdev->dev, "message read\n");
129 if (!buffer) {
edf1eed4 130 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
15d4acc5
TW
131 dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
132 MEI_HDR_PRM(mei_hdr));
fb7d879f
OW
133 }
134
135 return 0;
136}
137
fb7d879f
OW
138/**
139 * _mei_irq_thread_close - processes close related operation.
140 *
141 * @dev: the device structure.
142 * @slots: free slots.
143 * @cb_pos: callback block.
144 * @cl: private data of the file object.
145 * @cmpl_list: complete list.
146 *
147 * returns 0, OK; otherwise, error.
148 */
149static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
150 struct mei_cl_cb *cb_pos,
151 struct mei_cl *cl,
fb601adb 152 struct mei_cl_cb *cmpl_list)
fb7d879f 153{
b45f3ccf 154 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
aeba4a06 155 sizeof(struct hbm_client_connect_request)))
b45f3ccf 156 return -EBADMSG;
fb7d879f 157
aeba4a06 158 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
b45f3ccf 159
8120e720 160 if (mei_hbm_cl_disconnect_req(dev, cl)) {
b45f3ccf 161 cl->status = 0;
ebb108ef 162 cb_pos->buf_idx = 0;
fb601adb 163 list_move_tail(&cb_pos->list, &cmpl_list->list);
b45f3ccf 164 return -EMSGSIZE;
fb7d879f 165 } else {
b45f3ccf
TW
166 cl->state = MEI_FILE_DISCONNECTING;
167 cl->status = 0;
ebb108ef 168 cb_pos->buf_idx = 0;
fb601adb 169 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
b45f3ccf 170 cl->timer_count = MEI_CONNECT_TIMEOUT;
fb7d879f
OW
171 }
172
173 return 0;
174}
175
fb7d879f
OW
176
177/**
178 * _mei_hb_read - processes read related operation.
179 *
180 * @dev: the device structure.
181 * @slots: free slots.
182 * @cb_pos: callback block.
183 * @cl: private data of the file object.
184 * @cmpl_list: complete list.
185 *
186 * returns 0, OK; otherwise, error.
187 */
188static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
189 struct mei_cl_cb *cb_pos,
190 struct mei_cl *cl,
fb601adb 191 struct mei_cl_cb *cmpl_list)
fb7d879f 192{
1e69d64a 193 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
fb7d879f 194 sizeof(struct hbm_flow_control))) {
fb7d879f 195 /* return the cancel routine */
fb601adb 196 list_del(&cb_pos->list);
fb7d879f
OW
197 return -EBADMSG;
198 }
199
7bdf72d3
TW
200 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
201
8120e720 202 if (mei_hbm_cl_flow_control_req(dev, cl)) {
1ccb7b62 203 cl->status = -ENODEV;
ebb108ef 204 cb_pos->buf_idx = 0;
fb601adb 205 list_move_tail(&cb_pos->list, &cmpl_list->list);
1ccb7b62
TW
206 return -ENODEV;
207 }
fb601adb 208 list_move_tail(&cb_pos->list, &dev->read_list.list);
1ccb7b62 209
fb7d879f
OW
210 return 0;
211}
212
213
214/**
215 * _mei_irq_thread_ioctl - processes ioctl related operation.
216 *
217 * @dev: the device structure.
218 * @slots: free slots.
219 * @cb_pos: callback block.
220 * @cl: private data of the file object.
221 * @cmpl_list: complete list.
222 *
223 * returns 0, OK; otherwise, error.
224 */
225static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
226 struct mei_cl_cb *cb_pos,
227 struct mei_cl *cl,
fb601adb 228 struct mei_cl_cb *cmpl_list)
fb7d879f 229{
b45f3ccf 230 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
fb7d879f 231 sizeof(struct hbm_client_connect_request))) {
fb7d879f 232 /* return the cancel routine */
fb601adb 233 list_del(&cb_pos->list);
fb7d879f
OW
234 return -EBADMSG;
235 }
236
b45f3ccf 237 cl->state = MEI_FILE_CONNECTING;
8120e720
TW
238 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
239 if (mei_hbm_cl_connect_req(dev, cl)) {
b45f3ccf 240 cl->status = -ENODEV;
ebb108ef 241 cb_pos->buf_idx = 0;
fb601adb 242 list_del(&cb_pos->list);
b45f3ccf
TW
243 return -ENODEV;
244 } else {
fb601adb 245 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
b45f3ccf
TW
246 cl->timer_count = MEI_CONNECT_TIMEOUT;
247 }
fb7d879f
OW
248 return 0;
249}
250
251/**
ea3b5fb7 252 * mei_irq_thread_write_complete - write messages to device.
fb7d879f
OW
253 *
254 * @dev: the device structure.
255 * @slots: free slots.
ea3b5fb7 256 * @cb: callback block.
fb7d879f
OW
257 * @cmpl_list: complete list.
258 *
259 * returns 0, OK; otherwise, error.
260 */
ea3b5fb7
TW
261static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
262 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
fb7d879f 263{
e46f1874 264 struct mei_msg_hdr mei_hdr;
ea3b5fb7
TW
265 struct mei_cl *cl = cb->cl;
266 size_t len = cb->request_buffer.size - cb->buf_idx;
267 size_t msg_slots = mei_data2slots(len);
268
e46f1874
TW
269 mei_hdr.host_addr = cl->host_client_id;
270 mei_hdr.me_addr = cl->me_client_id;
271 mei_hdr.reserved = 0;
fb7d879f 272
ea3b5fb7 273 if (*slots >= msg_slots) {
e46f1874
TW
274 mei_hdr.length = len;
275 mei_hdr.msg_complete = 1;
ea3b5fb7 276 /* Split the message only if we can write the whole host buffer */
24aadc80 277 } else if (*slots == dev->hbuf_depth) {
ea3b5fb7
TW
278 msg_slots = *slots;
279 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
e46f1874
TW
280 mei_hdr.length = len;
281 mei_hdr.msg_complete = 0;
fb7d879f 282 } else {
ea3b5fb7
TW
283 /* wait for next time the host buffer is empty */
284 return 0;
fb7d879f
OW
285 }
286
ea3b5fb7
TW
287 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
288 cb->request_buffer.size, cb->buf_idx);
e46f1874 289 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
ea3b5fb7
TW
290
291 *slots -= msg_slots;
e46f1874 292 if (mei_write_message(dev, &mei_hdr,
438763f3 293 cb->request_buffer.data + cb->buf_idx)) {
ea3b5fb7
TW
294 cl->status = -ENODEV;
295 list_move_tail(&cb->list, &cmpl_list->list);
296 return -ENODEV;
297 }
298
299 if (mei_flow_ctrl_reduce(dev, cl))
300 return -ENODEV;
301
302 cl->status = 0;
e46f1874
TW
303 cb->buf_idx += mei_hdr.length;
304 if (mei_hdr.msg_complete)
ea3b5fb7
TW
305 list_move_tail(&cb->list, &dev->write_waiting_list.list);
306
fb7d879f
OW
307 return 0;
308}
309
fb7d879f
OW
310/**
311 * mei_irq_thread_read_handler - bottom half read routine after ISR to
312 * handle the read processing.
313 *
314 * @cmpl_list: An instance of our list structure
315 * @dev: the device structure
316 * @slots: slots to read.
317 *
318 * returns 0 on success, <0 on failure.
319 */
fb601adb 320static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
fb7d879f
OW
321 struct mei_device *dev,
322 s32 *slots)
323{
324 struct mei_msg_hdr *mei_hdr;
325 struct mei_cl *cl_pos = NULL;
326 struct mei_cl *cl_next = NULL;
327 int ret = 0;
328
329 if (!dev->rd_msg_hdr) {
330 dev->rd_msg_hdr = mei_mecbrw_read(dev);
331 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
332 (*slots)--;
333 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
334 }
335 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
15d4acc5 336 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
fb7d879f
OW
337
338 if (mei_hdr->reserved || !dev->rd_msg_hdr) {
339 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
340 ret = -EBADMSG;
341 goto end;
342 }
343
344 if (mei_hdr->host_addr || mei_hdr->me_addr) {
345 list_for_each_entry_safe(cl_pos, cl_next,
346 &dev->file_list, link) {
347 dev_dbg(&dev->pdev->dev,
348 "list_for_each_entry_safe read host"
349 " client = %d, ME client = %d\n",
350 cl_pos->host_client_id,
351 cl_pos->me_client_id);
352 if (cl_pos->host_client_id == mei_hdr->host_addr &&
353 cl_pos->me_client_id == mei_hdr->me_addr)
354 break;
355 }
356
357 if (&cl_pos->link == &dev->file_list) {
358 dev_dbg(&dev->pdev->dev, "corrupted message header\n");
359 ret = -EBADMSG;
360 goto end;
361 }
362 }
363 if (((*slots) * sizeof(u32)) < mei_hdr->length) {
364 dev_dbg(&dev->pdev->dev,
365 "we can't read the message slots =%08x.\n",
366 *slots);
367 /* we can't read the message */
368 ret = -ERANGE;
369 goto end;
370 }
371
372 /* decide where to read the message too */
373 if (!mei_hdr->host_addr) {
374 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
bb1b0133 375 mei_hbm_dispatch(dev, mei_hdr);
fb7d879f
OW
376 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
377 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
378 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
379 (dev->iamthif_state == MEI_IAMTHIF_READING)) {
380 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
15d4acc5
TW
381
382 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
19838fb8
TW
383
384 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
fb7d879f
OW
385 if (ret)
386 goto end;
fb7d879f
OW
387 } else {
388 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
389 ret = mei_irq_thread_read_client_message(cmpl_list,
390 dev, mei_hdr);
391 if (ret)
392 goto end;
393
394 }
395
396 /* reset the number of slots and header */
397 *slots = mei_count_full_read_slots(dev);
398 dev->rd_msg_hdr = 0;
399
400 if (*slots == -EOVERFLOW) {
401 /* overflow - reset */
402 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
403 /* set the event since message has been read */
404 ret = -ERANGE;
405 goto end;
406 }
407end:
408 return ret;
409}
410
411
412/**
413 * mei_irq_thread_write_handler - bottom half write routine after
414 * ISR to handle the write processing.
415 *
fb7d879f 416 * @dev: the device structure
9a84d616 417 * @cmpl_list: An instance of our list structure
fb7d879f
OW
418 *
419 * returns 0 on success, <0 on failure.
420 */
9a84d616
TW
421static int mei_irq_thread_write_handler(struct mei_device *dev,
422 struct mei_cl_cb *cmpl_list)
fb7d879f
OW
423{
424
425 struct mei_cl *cl;
b7cd2d9f 426 struct mei_cl_cb *pos = NULL, *next = NULL;
fb601adb 427 struct mei_cl_cb *list;
9a84d616 428 s32 slots;
fb7d879f
OW
429 int ret;
430
726917f0 431 if (!mei_hbuf_is_empty(dev)) {
fb7d879f
OW
432 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
433 return 0;
434 }
9a84d616
TW
435 slots = mei_hbuf_empty_slots(dev);
436 if (slots <= 0)
7d5e0e59
TW
437 return -EMSGSIZE;
438
fb7d879f
OW
439 /* complete all waiting for write CB */
440 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
441
442 list = &dev->write_waiting_list;
fb601adb 443 list_for_each_entry_safe(pos, next, &list->list, list) {
db3ed431 444 cl = pos->cl;
b7cd2d9f
TW
445 if (cl == NULL)
446 continue;
447
448 cl->status = 0;
fb601adb 449 list_del(&pos->list);
b7cd2d9f 450 if (MEI_WRITING == cl->writing_state &&
4b8960b4
TW
451 pos->fop_type == MEI_FOP_WRITE &&
452 cl != &dev->iamthif_cl) {
483136ea 453 dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
b7cd2d9f 454 cl->writing_state = MEI_WRITE_COMPLETE;
fb601adb 455 list_add_tail(&pos->list, &cmpl_list->list);
b7cd2d9f
TW
456 }
457 if (cl == &dev->iamthif_cl) {
458 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
459 if (dev->iamthif_flow_control_pending) {
9a84d616 460 ret = mei_amthif_irq_read(dev, &slots);
b7cd2d9f
TW
461 if (ret)
462 return ret;
fb7d879f 463 }
fb7d879f
OW
464 }
465 }
466
c216fdeb
TW
467 if (dev->wd_state == MEI_WD_STOPPING) {
468 dev->wd_state = MEI_WD_IDLE;
fb7d879f 469 wake_up_interruptible(&dev->wait_stop_wd);
fb7d879f
OW
470 }
471
5fb54fb4
TW
472 if (dev->wr_ext_msg.hdr.length) {
473 mei_write_message(dev, &dev->wr_ext_msg.hdr,
438763f3 474 dev->wr_ext_msg.data);
9a84d616 475 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
5fb54fb4 476 dev->wr_ext_msg.hdr.length = 0;
fb7d879f 477 }
b210d750 478 if (dev->dev_state == MEI_DEV_ENABLED) {
fb7d879f 479 if (dev->wd_pending &&
483136ea 480 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
fb7d879f
OW
481 if (mei_wd_send(dev))
482 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
483136ea
TW
483 else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
484 return -ENODEV;
fb7d879f 485
eb9af0ac 486 dev->wd_pending = false;
fb7d879f 487
c216fdeb 488 if (dev->wd_state == MEI_WD_RUNNING)
9a84d616 489 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
d242a0af 490 else
9a84d616 491 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
fb7d879f
OW
492 }
493 }
fb7d879f
OW
494
495 /* complete control write list CB */
c8372094 496 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
fb601adb 497 list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
db3ed431 498 cl = pos->cl;
c8372094 499 if (!cl) {
fb601adb 500 list_del(&pos->list);
c8372094
TW
501 return -ENODEV;
502 }
4b8960b4
TW
503 switch (pos->fop_type) {
504 case MEI_FOP_CLOSE:
c8372094 505 /* send disconnect message */
9a84d616
TW
506 ret = _mei_irq_thread_close(dev, &slots, pos,
507 cl, cmpl_list);
c8372094
TW
508 if (ret)
509 return ret;
fb7d879f 510
c8372094 511 break;
4b8960b4 512 case MEI_FOP_READ:
c8372094 513 /* send flow control message */
9a84d616
TW
514 ret = _mei_irq_thread_read(dev, &slots, pos,
515 cl, cmpl_list);
c8372094
TW
516 if (ret)
517 return ret;
fb7d879f 518
c8372094 519 break;
4b8960b4 520 case MEI_FOP_IOCTL:
c8372094 521 /* connect message */
e8cd29d8 522 if (mei_other_client_is_connecting(dev, cl))
c8372094 523 continue;
9a84d616
TW
524 ret = _mei_irq_thread_ioctl(dev, &slots, pos,
525 cl, cmpl_list);
c8372094
TW
526 if (ret)
527 return ret;
fb7d879f 528
c8372094 529 break;
fb7d879f 530
c8372094
TW
531 default:
532 BUG();
fb7d879f 533 }
c8372094 534
fb7d879f
OW
535 }
536 /* complete write list CB */
b7cd2d9f 537 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
fb601adb 538 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
db3ed431 539 cl = pos->cl;
b7cd2d9f
TW
540 if (cl == NULL)
541 continue;
be9d87a7
TW
542 if (mei_flow_ctrl_creds(dev, cl) <= 0) {
543 dev_dbg(&dev->pdev->dev,
544 "No flow control credentials for client %d, not sending.\n",
545 cl->host_client_id);
546 continue;
547 }
b7cd2d9f 548
be9d87a7 549 if (cl == &dev->iamthif_cl)
9a84d616 550 ret = mei_amthif_irq_write_complete(dev, &slots,
24c656e5 551 pos, cmpl_list);
be9d87a7
TW
552 else
553 ret = mei_irq_thread_write_complete(dev, &slots, pos,
554 cmpl_list);
555 if (ret)
556 return ret;
b7cd2d9f 557
fb7d879f
OW
558 }
559 return 0;
560}
561
562
563
564/**
565 * mei_timer - timer function.
566 *
567 * @work: pointer to the work_struct structure
568 *
569 * NOTE: This function is called by timer interrupt work
570 */
a61c6530 571void mei_timer(struct work_struct *work)
fb7d879f
OW
572{
573 unsigned long timeout;
574 struct mei_cl *cl_pos = NULL;
575 struct mei_cl *cl_next = NULL;
fb7d879f
OW
576 struct mei_cl_cb *cb_pos = NULL;
577 struct mei_cl_cb *cb_next = NULL;
578
579 struct mei_device *dev = container_of(work,
a61c6530 580 struct mei_device, timer_work.work);
fb7d879f
OW
581
582
583 mutex_lock(&dev->device_lock);
b210d750
TW
584 if (dev->dev_state != MEI_DEV_ENABLED) {
585 if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
fb7d879f
OW
586 if (dev->init_clients_timer) {
587 if (--dev->init_clients_timer == 0) {
588 dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
589 dev->init_clients_state);
590 mei_reset(dev, 1);
591 }
592 }
593 }
594 goto out;
595 }
596 /*** connect/disconnect timeouts ***/
597 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
598 if (cl_pos->timer_count) {
599 if (--cl_pos->timer_count == 0) {
600 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
601 mei_reset(dev, 1);
602 goto out;
603 }
604 }
605 }
606
fb7d879f
OW
607 if (dev->iamthif_stall_timer) {
608 if (--dev->iamthif_stall_timer == 0) {
32de21f7 609 dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n");
fb7d879f
OW
610 mei_reset(dev, 1);
611 dev->iamthif_msg_buf_size = 0;
612 dev->iamthif_msg_buf_index = 0;
eb9af0ac
TW
613 dev->iamthif_canceled = false;
614 dev->iamthif_ioctl = true;
fb7d879f
OW
615 dev->iamthif_state = MEI_IAMTHIF_IDLE;
616 dev->iamthif_timer = 0;
617
601a1efa
TW
618 mei_io_cb_free(dev->iamthif_current_cb);
619 dev->iamthif_current_cb = NULL;
fb7d879f
OW
620
621 dev->iamthif_file_object = NULL;
19838fb8 622 mei_amthif_run_next_cmd(dev);
fb7d879f
OW
623 }
624 }
625
626 if (dev->iamthif_timer) {
627
628 timeout = dev->iamthif_timer +
3870c320 629 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
fb7d879f
OW
630
631 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
632 dev->iamthif_timer);
633 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
634 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
635 if (time_after(jiffies, timeout)) {
636 /*
637 * User didn't read the AMTHI data on time (15sec)
638 * freeing AMTHI for other requests
639 */
640
641 dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
642
e773efc4
TW
643 list_for_each_entry_safe(cb_pos, cb_next,
644 &dev->amthif_rd_complete_list.list, list) {
fb7d879f 645
b7cd2d9f 646 cl_pos = cb_pos->file_object->private_data;
fb7d879f 647
b7cd2d9f
TW
648 /* Finding the AMTHI entry. */
649 if (cl_pos == &dev->iamthif_cl)
fb601adb 650 list_del(&cb_pos->list);
fb7d879f 651 }
601a1efa
TW
652 mei_io_cb_free(dev->iamthif_current_cb);
653 dev->iamthif_current_cb = NULL;
fb7d879f
OW
654
655 dev->iamthif_file_object->private_data = NULL;
656 dev->iamthif_file_object = NULL;
fb7d879f 657 dev->iamthif_timer = 0;
19838fb8 658 mei_amthif_run_next_cmd(dev);
fb7d879f
OW
659
660 }
661 }
662out:
441ab50f
TW
663 schedule_delayed_work(&dev->timer_work, 2 * HZ);
664 mutex_unlock(&dev->device_lock);
fb7d879f
OW
665}
666
667/**
668 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt
669 * processing.
670 *
671 * @irq: The irq number
672 * @dev_id: pointer to the device structure
673 *
674 * returns irqreturn_t
675 *
676 */
677irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
678{
679 struct mei_device *dev = (struct mei_device *) dev_id;
fb601adb 680 struct mei_cl_cb complete_list;
fb7d879f
OW
681 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
682 struct mei_cl *cl;
683 s32 slots;
684 int rets;
685 bool bus_message_received;
686
687
688 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
689 /* initialize our complete list */
690 mutex_lock(&dev->device_lock);
0288c7c9 691 mei_io_list_init(&complete_list);
fb7d879f 692 dev->host_hw_state = mei_hcsr_read(dev);
4f61a7ad
TW
693
694 /* Ack the interrupt here
5f9092f3 695 * In case of MSI we don't go through the quick handler */
4f61a7ad 696 if (pci_dev_msi_enabled(dev->pdev))
3a65dd4e 697 mei_clear_interrupts(dev);
4f61a7ad 698
fb7d879f
OW
699 dev->me_hw_state = mei_mecsr_read(dev);
700
701 /* check if ME wants a reset */
702 if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
b210d750
TW
703 dev->dev_state != MEI_DEV_RESETING &&
704 dev->dev_state != MEI_DEV_INITIALIZING) {
fb7d879f
OW
705 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
706 mei_reset(dev, 1);
707 mutex_unlock(&dev->device_lock);
708 return IRQ_HANDLED;
709 }
710
711 /* check if we need to start the dev */
712 if ((dev->host_hw_state & H_RDY) == 0) {
713 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
714 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
715 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
716 mei_hcsr_set(dev);
b210d750 717 dev->dev_state = MEI_DEV_INIT_CLIENTS;
fb7d879f
OW
718 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
719 /* link is established
720 * start sending messages.
721 */
8120e720 722 mei_hbm_start_req(dev);
fb7d879f
OW
723 mutex_unlock(&dev->device_lock);
724 return IRQ_HANDLED;
725 } else {
726 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
727 mutex_unlock(&dev->device_lock);
728 return IRQ_HANDLED;
729 }
730 }
5f9092f3 731 /* check slots available for reading */
fb7d879f 732 slots = mei_count_full_read_slots(dev);
5fb54fb4
TW
733 while (slots > 0) {
734 /* we have urgent data to send so break the read */
735 if (dev->wr_ext_msg.hdr.length)
736 break;
737 dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
fb7d879f
OW
738 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
739 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
740 if (rets)
741 goto end;
742 }
9a84d616 743 rets = mei_irq_thread_write_handler(dev, &complete_list);
fb7d879f
OW
744end:
745 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
746 dev->host_hw_state = mei_hcsr_read(dev);
726917f0 747 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
fb7d879f
OW
748
749 bus_message_received = false;
750 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
751 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
752 bus_message_received = true;
753 }
754 mutex_unlock(&dev->device_lock);
755 if (bus_message_received) {
756 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
757 wake_up_interruptible(&dev->wait_recvd_msg);
758 bus_message_received = false;
759 }
fb601adb 760 if (list_empty(&complete_list.list))
fb7d879f
OW
761 return IRQ_HANDLED;
762
763
fb601adb 764 list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
db3ed431 765 cl = cb_pos->cl;
fb601adb 766 list_del(&cb_pos->list);
fb7d879f
OW
767 if (cl) {
768 if (cl != &dev->iamthif_cl) {
769 dev_dbg(&dev->pdev->dev, "completing call back.\n");
770 _mei_cmpl(cl, cb_pos);
771 cb_pos = NULL;
772 } else if (cl == &dev->iamthif_cl) {
19838fb8 773 mei_amthif_complete(dev, cb_pos);
fb7d879f
OW
774 }
775 }
776 }
777 return IRQ_HANDLED;
778}