aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/interrupt.c')
-rw-r--r--drivers/misc/mei/interrupt.c656
1 files changed, 43 insertions, 613 deletions
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 04fa2134615e..3535b2676c97 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -21,41 +21,21 @@
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/jiffies.h> 22#include <linux/jiffies.h>
23 23
24#include "mei_dev.h"
25#include <linux/mei.h> 24#include <linux/mei.h>
26#include "hw.h"
27#include "interface.h"
28
29
30/**
31 * mei_interrupt_quick_handler - The ISR of the MEI device
32 *
33 * @irq: The irq number
34 * @dev_id: pointer to the device structure
35 *
36 * returns irqreturn_t
37 */
38irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
39{
40 struct mei_device *dev = (struct mei_device *) dev_id;
41 u32 csr_reg = mei_hcsr_read(dev);
42
43 if ((csr_reg & H_IS) != H_IS)
44 return IRQ_NONE;
45 25
46 /* clear H_IS bit in H_CSR */ 26#include "mei_dev.h"
47 mei_reg_write(dev, H_CSR, csr_reg); 27#include "hbm.h"
28#include "hw-me.h"
29#include "client.h"
48 30
49 return IRQ_WAKE_THREAD;
50}
51 31
52/** 32/**
53 * _mei_cmpl - processes completed operation. 33 * mei_complete_handler - processes completed operation.
54 * 34 *
55 * @cl: private data of the file object. 35 * @cl: private data of the file object.
56 * @cb_pos: callback block. 36 * @cb_pos: callback block.
57 */ 37 */
58static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) 38void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
59{ 39{
60 if (cb_pos->fop_type == MEI_FOP_WRITE) { 40 if (cb_pos->fop_type == MEI_FOP_WRITE) {
61 mei_io_cb_free(cb_pos); 41 mei_io_cb_free(cb_pos);
@@ -150,8 +130,8 @@ quit:
150 dev_dbg(&dev->pdev->dev, "message read\n"); 130 dev_dbg(&dev->pdev->dev, "message read\n");
151 if (!buffer) { 131 if (!buffer) {
152 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); 132 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
153 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n", 133 dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
154 *(u32 *) dev->rd_msg_buf); 134 MEI_HDR_PRM(mei_hdr));
155 } 135 }
156 136
157 return 0; 137 return 0;
@@ -179,7 +159,7 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
179 159
180 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 160 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
181 161
182 if (mei_disconnect(dev, cl)) { 162 if (mei_hbm_cl_disconnect_req(dev, cl)) {
183 cl->status = 0; 163 cl->status = 0;
184 cb_pos->buf_idx = 0; 164 cb_pos->buf_idx = 0;
185 list_move_tail(&cb_pos->list, &cmpl_list->list); 165 list_move_tail(&cb_pos->list, &cmpl_list->list);
@@ -195,440 +175,6 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
195 return 0; 175 return 0;
196} 176}
197 177
198/**
199 * is_treat_specially_client - checks if the message belongs
200 * to the file private data.
201 *
202 * @cl: private data of the file object
203 * @rs: connect response bus message
204 *
205 */
206static bool is_treat_specially_client(struct mei_cl *cl,
207 struct hbm_client_connect_response *rs)
208{
209
210 if (cl->host_client_id == rs->host_addr &&
211 cl->me_client_id == rs->me_addr) {
212 if (!rs->status) {
213 cl->state = MEI_FILE_CONNECTED;
214 cl->status = 0;
215
216 } else {
217 cl->state = MEI_FILE_DISCONNECTED;
218 cl->status = -ENODEV;
219 }
220 cl->timer_count = 0;
221
222 return true;
223 }
224 return false;
225}
226
227/**
228 * mei_client_connect_response - connects to response irq routine
229 *
230 * @dev: the device structure
231 * @rs: connect response bus message
232 */
233static void mei_client_connect_response(struct mei_device *dev,
234 struct hbm_client_connect_response *rs)
235{
236
237 struct mei_cl *cl;
238 struct mei_cl_cb *pos = NULL, *next = NULL;
239
240 dev_dbg(&dev->pdev->dev,
241 "connect_response:\n"
242 "ME Client = %d\n"
243 "Host Client = %d\n"
244 "Status = %d\n",
245 rs->me_addr,
246 rs->host_addr,
247 rs->status);
248
249 /* if WD or iamthif client treat specially */
250
251 if (is_treat_specially_client(&(dev->wd_cl), rs)) {
252 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
253 mei_watchdog_register(dev);
254
255 return;
256 }
257
258 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
259 dev->iamthif_state = MEI_IAMTHIF_IDLE;
260 return;
261 }
262 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
263
264 cl = pos->cl;
265 if (!cl) {
266 list_del(&pos->list);
267 return;
268 }
269 if (pos->fop_type == MEI_FOP_IOCTL) {
270 if (is_treat_specially_client(cl, rs)) {
271 list_del(&pos->list);
272 cl->status = 0;
273 cl->timer_count = 0;
274 break;
275 }
276 }
277 }
278}
279
280/**
281 * mei_client_disconnect_response - disconnects from response irq routine
282 *
283 * @dev: the device structure
284 * @rs: disconnect response bus message
285 */
286static void mei_client_disconnect_response(struct mei_device *dev,
287 struct hbm_client_connect_response *rs)
288{
289 struct mei_cl *cl;
290 struct mei_cl_cb *pos = NULL, *next = NULL;
291
292 dev_dbg(&dev->pdev->dev,
293 "disconnect_response:\n"
294 "ME Client = %d\n"
295 "Host Client = %d\n"
296 "Status = %d\n",
297 rs->me_addr,
298 rs->host_addr,
299 rs->status);
300
301 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
302 cl = pos->cl;
303
304 if (!cl) {
305 list_del(&pos->list);
306 return;
307 }
308
309 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
310 if (cl->host_client_id == rs->host_addr &&
311 cl->me_client_id == rs->me_addr) {
312
313 list_del(&pos->list);
314 if (!rs->status)
315 cl->state = MEI_FILE_DISCONNECTED;
316
317 cl->status = 0;
318 cl->timer_count = 0;
319 break;
320 }
321 }
322}
323
324/**
325 * same_flow_addr - tells if they have the same address.
326 *
327 * @file: private data of the file object.
328 * @flow: flow control.
329 *
330 * returns !=0, same; 0,not.
331 */
332static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
333{
334 return (cl->host_client_id == flow->host_addr &&
335 cl->me_client_id == flow->me_addr);
336}
337
338/**
339 * add_single_flow_creds - adds single buffer credentials.
340 *
341 * @file: private data ot the file object.
342 * @flow: flow control.
343 */
344static void add_single_flow_creds(struct mei_device *dev,
345 struct hbm_flow_control *flow)
346{
347 struct mei_me_client *client;
348 int i;
349
350 for (i = 0; i < dev->me_clients_num; i++) {
351 client = &dev->me_clients[i];
352 if (client && flow->me_addr == client->client_id) {
353 if (client->props.single_recv_buf) {
354 client->mei_flow_ctrl_creds++;
355 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
356 flow->me_addr);
357 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
358 client->mei_flow_ctrl_creds);
359 } else {
360 BUG(); /* error in flow control */
361 }
362 }
363 }
364}
365
366/**
367 * mei_client_flow_control_response - flow control response irq routine
368 *
369 * @dev: the device structure
370 * @flow_control: flow control response bus message
371 */
372static void mei_client_flow_control_response(struct mei_device *dev,
373 struct hbm_flow_control *flow_control)
374{
375 struct mei_cl *cl_pos = NULL;
376 struct mei_cl *cl_next = NULL;
377
378 if (!flow_control->host_addr) {
379 /* single receive buffer */
380 add_single_flow_creds(dev, flow_control);
381 } else {
382 /* normal connection */
383 list_for_each_entry_safe(cl_pos, cl_next,
384 &dev->file_list, link) {
385 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
386
387 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
388 cl_pos->host_client_id,
389 cl_pos->me_client_id);
390 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
391 flow_control->host_addr,
392 flow_control->me_addr);
393 if (same_flow_addr(cl_pos, flow_control)) {
394 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n",
395 flow_control->host_addr,
396 flow_control->me_addr);
397 cl_pos->mei_flow_ctrl_creds++;
398 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
399 cl_pos->mei_flow_ctrl_creds);
400 break;
401 }
402 }
403 }
404}
405
406/**
407 * same_disconn_addr - tells if they have the same address
408 *
409 * @file: private data of the file object.
410 * @disconn: disconnection request.
411 *
412 * returns !=0, same; 0,not.
413 */
414static int same_disconn_addr(struct mei_cl *cl,
415 struct hbm_client_connect_request *req)
416{
417 return (cl->host_client_id == req->host_addr &&
418 cl->me_client_id == req->me_addr);
419}
420
421/**
422 * mei_client_disconnect_request - disconnects from request irq routine
423 *
424 * @dev: the device structure.
425 * @disconnect_req: disconnect request bus message.
426 */
427static void mei_client_disconnect_request(struct mei_device *dev,
428 struct hbm_client_connect_request *disconnect_req)
429{
430 struct hbm_client_connect_response *disconnect_res;
431 struct mei_cl *pos, *next;
432 const size_t len = sizeof(struct hbm_client_connect_response);
433
434 list_for_each_entry_safe(pos, next, &dev->file_list, link) {
435 if (same_disconn_addr(pos, disconnect_req)) {
436 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
437 disconnect_req->host_addr,
438 disconnect_req->me_addr);
439 pos->state = MEI_FILE_DISCONNECTED;
440 pos->timer_count = 0;
441 if (pos == &dev->wd_cl)
442 dev->wd_pending = false;
443 else if (pos == &dev->iamthif_cl)
444 dev->iamthif_timer = 0;
445
446 /* prepare disconnect response */
447 (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
448 disconnect_res =
449 (struct hbm_client_connect_response *)
450 &dev->wr_ext_msg.data;
451 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
452 disconnect_res->host_addr = pos->host_client_id;
453 disconnect_res->me_addr = pos->me_client_id;
454 disconnect_res->status = 0;
455 break;
456 }
457 }
458}
459
460/**
461 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
462 * handle the read bus message cmd processing.
463 *
464 * @dev: the device structure
465 * @mei_hdr: header of bus message
466 */
467static void mei_irq_thread_read_bus_message(struct mei_device *dev,
468 struct mei_msg_hdr *mei_hdr)
469{
470 struct mei_bus_message *mei_msg;
471 struct mei_me_client *me_client;
472 struct hbm_host_version_response *version_res;
473 struct hbm_client_connect_response *connect_res;
474 struct hbm_client_connect_response *disconnect_res;
475 struct hbm_client_connect_request *disconnect_req;
476 struct hbm_flow_control *flow_control;
477 struct hbm_props_response *props_res;
478 struct hbm_host_enum_response *enum_res;
479 struct hbm_host_stop_request *stop_req;
480
481 /* read the message to our buffer */
482 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
483 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
484 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
485
486 switch (mei_msg->hbm_cmd) {
487 case HOST_START_RES_CMD:
488 version_res = (struct hbm_host_version_response *) mei_msg;
489 if (version_res->host_version_supported) {
490 dev->version.major_version = HBM_MAJOR_VERSION;
491 dev->version.minor_version = HBM_MINOR_VERSION;
492 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
493 dev->init_clients_state == MEI_START_MESSAGE) {
494 dev->init_clients_timer = 0;
495 mei_host_enum_clients_message(dev);
496 } else {
497 dev->recvd_msg = false;
498 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
499 mei_reset(dev, 1);
500 return;
501 }
502 } else {
503 u32 *buf = dev->wr_msg_buf;
504 const size_t len = sizeof(struct hbm_host_stop_request);
505
506 dev->version = version_res->me_max_version;
507
508 /* send stop message */
509 mei_hdr = mei_hbm_hdr(&buf[0], len);
510 stop_req = (struct hbm_host_stop_request *)&buf[1];
511 memset(stop_req, 0, len);
512 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
513 stop_req->reason = DRIVER_STOP_REQUEST;
514
515 mei_write_message(dev, mei_hdr,
516 (unsigned char *)stop_req, len);
517 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
518 return;
519 }
520
521 dev->recvd_msg = true;
522 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
523 break;
524
525 case CLIENT_CONNECT_RES_CMD:
526 connect_res = (struct hbm_client_connect_response *) mei_msg;
527 mei_client_connect_response(dev, connect_res);
528 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
529 wake_up(&dev->wait_recvd_msg);
530 break;
531
532 case CLIENT_DISCONNECT_RES_CMD:
533 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
534 mei_client_disconnect_response(dev, disconnect_res);
535 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
536 wake_up(&dev->wait_recvd_msg);
537 break;
538
539 case MEI_FLOW_CONTROL_CMD:
540 flow_control = (struct hbm_flow_control *) mei_msg;
541 mei_client_flow_control_response(dev, flow_control);
542 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
543 break;
544
545 case HOST_CLIENT_PROPERTIES_RES_CMD:
546 props_res = (struct hbm_props_response *)mei_msg;
547 me_client = &dev->me_clients[dev->me_client_presentation_num];
548
549 if (props_res->status || !dev->me_clients) {
550 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
551 mei_reset(dev, 1);
552 return;
553 }
554
555 if (me_client->client_id != props_res->address) {
556 dev_err(&dev->pdev->dev,
557 "Host client properties reply mismatch\n");
558 mei_reset(dev, 1);
559
560 return;
561 }
562
563 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
564 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
565 dev_err(&dev->pdev->dev,
566 "Unexpected client properties reply\n");
567 mei_reset(dev, 1);
568
569 return;
570 }
571
572 me_client->props = props_res->client_properties;
573 dev->me_client_index++;
574 dev->me_client_presentation_num++;
575
576 mei_host_client_enumerate(dev);
577
578 break;
579
580 case HOST_ENUM_RES_CMD:
581 enum_res = (struct hbm_host_enum_response *) mei_msg;
582 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
583 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
584 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
585 dev->init_clients_timer = 0;
586 dev->me_client_presentation_num = 0;
587 dev->me_client_index = 0;
588 mei_allocate_me_clients_storage(dev);
589 dev->init_clients_state =
590 MEI_CLIENT_PROPERTIES_MESSAGE;
591
592 mei_host_client_enumerate(dev);
593 } else {
594 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
595 mei_reset(dev, 1);
596 return;
597 }
598 break;
599
600 case HOST_STOP_RES_CMD:
601 dev->dev_state = MEI_DEV_DISABLED;
602 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
603 mei_reset(dev, 1);
604 break;
605
606 case CLIENT_DISCONNECT_REQ_CMD:
607 /* search for client */
608 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
609 mei_client_disconnect_request(dev, disconnect_req);
610 break;
611
612 case ME_STOP_REQ_CMD:
613 {
614 /* prepare stop request: sent in next interrupt event */
615
616 const size_t len = sizeof(struct hbm_host_stop_request);
617
618 mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
619 stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
620 memset(stop_req, 0, len);
621 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
622 stop_req->reason = DRIVER_STOP_REQUEST;
623 break;
624 }
625 default:
626 BUG();
627 break;
628
629 }
630}
631
632 178
633/** 179/**
634 * _mei_hb_read - processes read related operation. 180 * _mei_hb_read - processes read related operation.
@@ -655,7 +201,7 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
655 201
656 *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); 202 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
657 203
658 if (mei_send_flow_control(dev, cl)) { 204 if (mei_hbm_cl_flow_control_req(dev, cl)) {
659 cl->status = -ENODEV; 205 cl->status = -ENODEV;
660 cb_pos->buf_idx = 0; 206 cb_pos->buf_idx = 0;
661 list_move_tail(&cb_pos->list, &cmpl_list->list); 207 list_move_tail(&cb_pos->list, &cmpl_list->list);
@@ -691,8 +237,8 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
691 } 237 }
692 238
693 cl->state = MEI_FILE_CONNECTING; 239 cl->state = MEI_FILE_CONNECTING;
694 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 240 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
695 if (mei_connect(dev, cl)) { 241 if (mei_hbm_cl_connect_req(dev, cl)) {
696 cl->status = -ENODEV; 242 cl->status = -ENODEV;
697 cb_pos->buf_idx = 0; 243 cb_pos->buf_idx = 0;
698 list_del(&cb_pos->list); 244 list_del(&cb_pos->list);
@@ -717,25 +263,24 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
717static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, 263static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
718 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) 264 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
719{ 265{
720 struct mei_msg_hdr *mei_hdr; 266 struct mei_msg_hdr mei_hdr;
721 struct mei_cl *cl = cb->cl; 267 struct mei_cl *cl = cb->cl;
722 size_t len = cb->request_buffer.size - cb->buf_idx; 268 size_t len = cb->request_buffer.size - cb->buf_idx;
723 size_t msg_slots = mei_data2slots(len); 269 size_t msg_slots = mei_data2slots(len);
724 270
725 mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; 271 mei_hdr.host_addr = cl->host_client_id;
726 mei_hdr->host_addr = cl->host_client_id; 272 mei_hdr.me_addr = cl->me_client_id;
727 mei_hdr->me_addr = cl->me_client_id; 273 mei_hdr.reserved = 0;
728 mei_hdr->reserved = 0;
729 274
730 if (*slots >= msg_slots) { 275 if (*slots >= msg_slots) {
731 mei_hdr->length = len; 276 mei_hdr.length = len;
732 mei_hdr->msg_complete = 1; 277 mei_hdr.msg_complete = 1;
733 /* Split the message only if we can write the whole host buffer */ 278 /* Split the message only if we can write the whole host buffer */
734 } else if (*slots == dev->hbuf_depth) { 279 } else if (*slots == dev->hbuf_depth) {
735 msg_slots = *slots; 280 msg_slots = *slots;
736 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 281 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
737 mei_hdr->length = len; 282 mei_hdr.length = len;
738 mei_hdr->msg_complete = 0; 283 mei_hdr.msg_complete = 0;
739 } else { 284 } else {
740 /* wait for next time the host buffer is empty */ 285 /* wait for next time the host buffer is empty */
741 return 0; 286 return 0;
@@ -743,23 +288,22 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
743 288
744 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", 289 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
745 cb->request_buffer.size, cb->buf_idx); 290 cb->request_buffer.size, cb->buf_idx);
746 dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n", 291 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
747 mei_hdr->length, mei_hdr->msg_complete);
748 292
749 *slots -= msg_slots; 293 *slots -= msg_slots;
750 if (mei_write_message(dev, mei_hdr, 294 if (mei_write_message(dev, &mei_hdr,
751 cb->request_buffer.data + cb->buf_idx, len)) { 295 cb->request_buffer.data + cb->buf_idx)) {
752 cl->status = -ENODEV; 296 cl->status = -ENODEV;
753 list_move_tail(&cb->list, &cmpl_list->list); 297 list_move_tail(&cb->list, &cmpl_list->list);
754 return -ENODEV; 298 return -ENODEV;
755 } 299 }
756 300
757 if (mei_flow_ctrl_reduce(dev, cl)) 301 if (mei_cl_flow_ctrl_reduce(cl))
758 return -ENODEV; 302 return -ENODEV;
759 303
760 cl->status = 0; 304 cl->status = 0;
761 cb->buf_idx += mei_hdr->length; 305 cb->buf_idx += mei_hdr.length;
762 if (mei_hdr->msg_complete) 306 if (mei_hdr.msg_complete)
763 list_move_tail(&cb->list, &dev->write_waiting_list.list); 307 list_move_tail(&cb->list, &dev->write_waiting_list.list);
764 308
765 return 0; 309 return 0;
@@ -769,15 +313,14 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
769 * mei_irq_thread_read_handler - bottom half read routine after ISR to 313 * mei_irq_thread_read_handler - bottom half read routine after ISR to
770 * handle the read processing. 314 * handle the read processing.
771 * 315 *
772 * @cmpl_list: An instance of our list structure
773 * @dev: the device structure 316 * @dev: the device structure
317 * @cmpl_list: An instance of our list structure
774 * @slots: slots to read. 318 * @slots: slots to read.
775 * 319 *
776 * returns 0 on success, <0 on failure. 320 * returns 0 on success, <0 on failure.
777 */ 321 */
778static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, 322int mei_irq_read_handler(struct mei_device *dev,
779 struct mei_device *dev, 323 struct mei_cl_cb *cmpl_list, s32 *slots)
780 s32 *slots)
781{ 324{
782 struct mei_msg_hdr *mei_hdr; 325 struct mei_msg_hdr *mei_hdr;
783 struct mei_cl *cl_pos = NULL; 326 struct mei_cl *cl_pos = NULL;
@@ -785,13 +328,13 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
785 int ret = 0; 328 int ret = 0;
786 329
787 if (!dev->rd_msg_hdr) { 330 if (!dev->rd_msg_hdr) {
788 dev->rd_msg_hdr = mei_mecbrw_read(dev); 331 dev->rd_msg_hdr = mei_read_hdr(dev);
789 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 332 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
790 (*slots)--; 333 (*slots)--;
791 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 334 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
792 } 335 }
793 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr; 336 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
794 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length); 337 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
795 338
796 if (mei_hdr->reserved || !dev->rd_msg_hdr) { 339 if (mei_hdr->reserved || !dev->rd_msg_hdr) {
797 dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); 340 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
@@ -830,19 +373,18 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
830 /* decide where to read the message too */ 373 /* decide where to read the message too */
831 if (!mei_hdr->host_addr) { 374 if (!mei_hdr->host_addr) {
832 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); 375 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
833 mei_irq_thread_read_bus_message(dev, mei_hdr); 376 mei_hbm_dispatch(dev, mei_hdr);
834 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 377 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
835 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 378 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
836 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 379 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
837 (dev->iamthif_state == MEI_IAMTHIF_READING)) { 380 (dev->iamthif_state == MEI_IAMTHIF_READING)) {
838 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); 381 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
839 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 382
840 mei_hdr->length); 383 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
841 384
842 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr); 385 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
843 if (ret) 386 if (ret)
844 goto end; 387 goto end;
845
846 } else { 388 } else {
847 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n"); 389 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
848 ret = mei_irq_thread_read_client_message(cmpl_list, 390 ret = mei_irq_thread_read_client_message(cmpl_list,
@@ -869,15 +411,15 @@ end:
869 411
870 412
871/** 413/**
872 * mei_irq_thread_write_handler - bottom half write routine after 414 * mei_irq_write_handler - dispatch write requests
873 * ISR to handle the write processing. 415 * after irq received
874 * 416 *
875 * @dev: the device structure 417 * @dev: the device structure
876 * @cmpl_list: An instance of our list structure 418 * @cmpl_list: An instance of our list structure
877 * 419 *
878 * returns 0 on success, <0 on failure. 420 * returns 0 on success, <0 on failure.
879 */ 421 */
880static int mei_irq_thread_write_handler(struct mei_device *dev, 422int mei_irq_write_handler(struct mei_device *dev,
881 struct mei_cl_cb *cmpl_list) 423 struct mei_cl_cb *cmpl_list)
882{ 424{
883 425
@@ -887,7 +429,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev,
887 s32 slots; 429 s32 slots;
888 int ret; 430 int ret;
889 431
890 if (!mei_hbuf_is_empty(dev)) { 432 if (!mei_hbuf_is_ready(dev)) {
891 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 433 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
892 return 0; 434 return 0;
893 } 435 }
@@ -930,16 +472,16 @@ static int mei_irq_thread_write_handler(struct mei_device *dev,
930 472
931 if (dev->wr_ext_msg.hdr.length) { 473 if (dev->wr_ext_msg.hdr.length) {
932 mei_write_message(dev, &dev->wr_ext_msg.hdr, 474 mei_write_message(dev, &dev->wr_ext_msg.hdr,
933 dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length); 475 dev->wr_ext_msg.data);
934 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length); 476 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
935 dev->wr_ext_msg.hdr.length = 0; 477 dev->wr_ext_msg.hdr.length = 0;
936 } 478 }
937 if (dev->dev_state == MEI_DEV_ENABLED) { 479 if (dev->dev_state == MEI_DEV_ENABLED) {
938 if (dev->wd_pending && 480 if (dev->wd_pending &&
939 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { 481 mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
940 if (mei_wd_send(dev)) 482 if (mei_wd_send(dev))
941 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); 483 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
942 else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) 484 else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
943 return -ENODEV; 485 return -ENODEV;
944 486
945 dev->wd_pending = false; 487 dev->wd_pending = false;
@@ -978,7 +520,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev,
978 break; 520 break;
979 case MEI_FOP_IOCTL: 521 case MEI_FOP_IOCTL:
980 /* connect message */ 522 /* connect message */
981 if (mei_other_client_is_connecting(dev, cl)) 523 if (mei_cl_is_other_connecting(cl))
982 continue; 524 continue;
983 ret = _mei_irq_thread_ioctl(dev, &slots, pos, 525 ret = _mei_irq_thread_ioctl(dev, &slots, pos,
984 cl, cmpl_list); 526 cl, cmpl_list);
@@ -998,7 +540,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev,
998 cl = pos->cl; 540 cl = pos->cl;
999 if (cl == NULL) 541 if (cl == NULL)
1000 continue; 542 continue;
1001 if (mei_flow_ctrl_creds(dev, cl) <= 0) { 543 if (mei_cl_flow_ctrl_creds(cl) <= 0) {
1002 dev_dbg(&dev->pdev->dev, 544 dev_dbg(&dev->pdev->dev,
1003 "No flow control credentials for client %d, not sending.\n", 545 "No flow control credentials for client %d, not sending.\n",
1004 cl->host_client_id); 546 cl->host_client_id);
@@ -1123,115 +665,3 @@ out:
1123 mutex_unlock(&dev->device_lock); 665 mutex_unlock(&dev->device_lock);
1124} 666}
1125 667
1126/**
1127 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt
1128 * processing.
1129 *
1130 * @irq: The irq number
1131 * @dev_id: pointer to the device structure
1132 *
1133 * returns irqreturn_t
1134 *
1135 */
1136irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1137{
1138 struct mei_device *dev = (struct mei_device *) dev_id;
1139 struct mei_cl_cb complete_list;
1140 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1141 struct mei_cl *cl;
1142 s32 slots;
1143 int rets;
1144 bool bus_message_received;
1145
1146
1147 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1148 /* initialize our complete list */
1149 mutex_lock(&dev->device_lock);
1150 mei_io_list_init(&complete_list);
1151 dev->host_hw_state = mei_hcsr_read(dev);
1152
1153 /* Ack the interrupt here
1154 * In case of MSI we don't go through the quick handler */
1155 if (pci_dev_msi_enabled(dev->pdev))
1156 mei_reg_write(dev, H_CSR, dev->host_hw_state);
1157
1158 dev->me_hw_state = mei_mecsr_read(dev);
1159
1160 /* check if ME wants a reset */
1161 if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
1162 dev->dev_state != MEI_DEV_RESETING &&
1163 dev->dev_state != MEI_DEV_INITIALIZING) {
1164 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1165 mei_reset(dev, 1);
1166 mutex_unlock(&dev->device_lock);
1167 return IRQ_HANDLED;
1168 }
1169
1170 /* check if we need to start the dev */
1171 if ((dev->host_hw_state & H_RDY) == 0) {
1172 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
1173 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1174 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1175 mei_hcsr_set(dev);
1176 dev->dev_state = MEI_DEV_INIT_CLIENTS;
1177 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1178 /* link is established
1179 * start sending messages.
1180 */
1181 mei_host_start_message(dev);
1182 mutex_unlock(&dev->device_lock);
1183 return IRQ_HANDLED;
1184 } else {
1185 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1186 mutex_unlock(&dev->device_lock);
1187 return IRQ_HANDLED;
1188 }
1189 }
1190 /* check slots available for reading */
1191 slots = mei_count_full_read_slots(dev);
1192 while (slots > 0) {
1193 /* we have urgent data to send so break the read */
1194 if (dev->wr_ext_msg.hdr.length)
1195 break;
1196 dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
1197 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1198 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1199 if (rets)
1200 goto end;
1201 }
1202 rets = mei_irq_thread_write_handler(dev, &complete_list);
1203end:
1204 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1205 dev->host_hw_state = mei_hcsr_read(dev);
1206 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
1207
1208 bus_message_received = false;
1209 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1210 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1211 bus_message_received = true;
1212 }
1213 mutex_unlock(&dev->device_lock);
1214 if (bus_message_received) {
1215 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
1216 wake_up_interruptible(&dev->wait_recvd_msg);
1217 bus_message_received = false;
1218 }
1219 if (list_empty(&complete_list.list))
1220 return IRQ_HANDLED;
1221
1222
1223 list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
1224 cl = cb_pos->cl;
1225 list_del(&cb_pos->list);
1226 if (cl) {
1227 if (cl != &dev->iamthif_cl) {
1228 dev_dbg(&dev->pdev->dev, "completing call back.\n");
1229 _mei_cmpl(cl, cb_pos);
1230 cb_pos = NULL;
1231 } else if (cl == &dev->iamthif_cl) {
1232 mei_amthif_complete(dev, cb_pos);
1233 }
1234 }
1235 }
1236 return IRQ_HANDLED;
1237}