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.c235
1 files changed, 5 insertions, 230 deletions
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index cd89b68fcf43..d4312a8e139a 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -208,7 +208,7 @@ static bool is_treat_specially_client(struct mei_cl *cl,
208 * @dev: the device structure 208 * @dev: the device structure
209 * @rs: connect response bus message 209 * @rs: connect response bus message
210 */ 210 */
211static void mei_client_connect_response(struct mei_device *dev, 211void mei_client_connect_response(struct mei_device *dev,
212 struct hbm_client_connect_response *rs) 212 struct hbm_client_connect_response *rs)
213{ 213{
214 214
@@ -261,8 +261,8 @@ static void mei_client_connect_response(struct mei_device *dev,
261 * @dev: the device structure 261 * @dev: the device structure
262 * @rs: disconnect response bus message 262 * @rs: disconnect response bus message
263 */ 263 */
264static void mei_client_disconnect_response(struct mei_device *dev, 264void mei_client_disconnect_response(struct mei_device *dev,
265 struct hbm_client_connect_response *rs) 265 struct hbm_client_connect_response *rs)
266{ 266{
267 struct mei_cl *cl; 267 struct mei_cl *cl;
268 struct mei_cl_cb *pos = NULL, *next = NULL; 268 struct mei_cl_cb *pos = NULL, *next = NULL;
@@ -347,7 +347,7 @@ static void add_single_flow_creds(struct mei_device *dev,
347 * @dev: the device structure 347 * @dev: the device structure
348 * @flow_control: flow control response bus message 348 * @flow_control: flow control response bus message
349 */ 349 */
350static void mei_client_flow_control_response(struct mei_device *dev, 350void mei_client_flow_control_response(struct mei_device *dev,
351 struct hbm_flow_control *flow_control) 351 struct hbm_flow_control *flow_control)
352{ 352{
353 struct mei_cl *cl_pos = NULL; 353 struct mei_cl *cl_pos = NULL;
@@ -381,231 +381,6 @@ static void mei_client_flow_control_response(struct mei_device *dev,
381 } 381 }
382} 382}
383 383
384/**
385 * same_disconn_addr - tells if they have the same address
386 *
387 * @file: private data of the file object.
388 * @disconn: disconnection request.
389 *
390 * returns !=0, same; 0,not.
391 */
392static int same_disconn_addr(struct mei_cl *cl,
393 struct hbm_client_connect_request *req)
394{
395 return (cl->host_client_id == req->host_addr &&
396 cl->me_client_id == req->me_addr);
397}
398
399/**
400 * mei_client_disconnect_request - disconnects from request irq routine
401 *
402 * @dev: the device structure.
403 * @disconnect_req: disconnect request bus message.
404 */
405static void mei_client_disconnect_request(struct mei_device *dev,
406 struct hbm_client_connect_request *disconnect_req)
407{
408 struct hbm_client_connect_response *disconnect_res;
409 struct mei_cl *pos, *next;
410 const size_t len = sizeof(struct hbm_client_connect_response);
411
412 list_for_each_entry_safe(pos, next, &dev->file_list, link) {
413 if (same_disconn_addr(pos, disconnect_req)) {
414 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
415 disconnect_req->host_addr,
416 disconnect_req->me_addr);
417 pos->state = MEI_FILE_DISCONNECTED;
418 pos->timer_count = 0;
419 if (pos == &dev->wd_cl)
420 dev->wd_pending = false;
421 else if (pos == &dev->iamthif_cl)
422 dev->iamthif_timer = 0;
423
424 /* prepare disconnect response */
425 (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
426 disconnect_res =
427 (struct hbm_client_connect_response *)
428 &dev->wr_ext_msg.data;
429 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
430 disconnect_res->host_addr = pos->host_client_id;
431 disconnect_res->me_addr = pos->me_client_id;
432 disconnect_res->status = 0;
433 break;
434 }
435 }
436}
437
438/**
439 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
440 * handle the read bus message cmd processing.
441 *
442 * @dev: the device structure
443 * @mei_hdr: header of bus message
444 */
445static void mei_irq_thread_read_bus_message(struct mei_device *dev,
446 struct mei_msg_hdr *hdr)
447{
448 struct mei_bus_message *mei_msg;
449 struct mei_me_client *me_client;
450 struct hbm_host_version_response *version_res;
451 struct hbm_client_connect_response *connect_res;
452 struct hbm_client_connect_response *disconnect_res;
453 struct hbm_client_connect_request *disconnect_req;
454 struct hbm_flow_control *flow_control;
455 struct hbm_props_response *props_res;
456 struct hbm_host_enum_response *enum_res;
457 struct hbm_host_stop_request *stop_req;
458
459 /* read the message to our buffer */
460 BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
461 mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
462 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
463
464 switch (mei_msg->hbm_cmd) {
465 case HOST_START_RES_CMD:
466 version_res = (struct hbm_host_version_response *) mei_msg;
467 if (version_res->host_version_supported) {
468 dev->version.major_version = HBM_MAJOR_VERSION;
469 dev->version.minor_version = HBM_MINOR_VERSION;
470 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
471 dev->init_clients_state == MEI_START_MESSAGE) {
472 dev->init_clients_timer = 0;
473 mei_host_enum_clients_message(dev);
474 } else {
475 dev->recvd_msg = false;
476 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
477 mei_reset(dev, 1);
478 return;
479 }
480 } else {
481 u32 *buf = dev->wr_msg_buf;
482 const size_t len = sizeof(struct hbm_host_stop_request);
483
484 dev->version = version_res->me_max_version;
485
486 /* send stop message */
487 hdr = mei_hbm_hdr(&buf[0], len);
488 stop_req = (struct hbm_host_stop_request *)&buf[1];
489 memset(stop_req, 0, len);
490 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
491 stop_req->reason = DRIVER_STOP_REQUEST;
492
493 mei_write_message(dev, hdr, (unsigned char *)stop_req);
494 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
495 return;
496 }
497
498 dev->recvd_msg = true;
499 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
500 break;
501
502 case CLIENT_CONNECT_RES_CMD:
503 connect_res = (struct hbm_client_connect_response *) mei_msg;
504 mei_client_connect_response(dev, connect_res);
505 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
506 wake_up(&dev->wait_recvd_msg);
507 break;
508
509 case CLIENT_DISCONNECT_RES_CMD:
510 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
511 mei_client_disconnect_response(dev, disconnect_res);
512 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
513 wake_up(&dev->wait_recvd_msg);
514 break;
515
516 case MEI_FLOW_CONTROL_CMD:
517 flow_control = (struct hbm_flow_control *) mei_msg;
518 mei_client_flow_control_response(dev, flow_control);
519 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
520 break;
521
522 case HOST_CLIENT_PROPERTIES_RES_CMD:
523 props_res = (struct hbm_props_response *)mei_msg;
524 me_client = &dev->me_clients[dev->me_client_presentation_num];
525
526 if (props_res->status || !dev->me_clients) {
527 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
528 mei_reset(dev, 1);
529 return;
530 }
531
532 if (me_client->client_id != props_res->address) {
533 dev_err(&dev->pdev->dev,
534 "Host client properties reply mismatch\n");
535 mei_reset(dev, 1);
536
537 return;
538 }
539
540 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
541 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
542 dev_err(&dev->pdev->dev,
543 "Unexpected client properties reply\n");
544 mei_reset(dev, 1);
545
546 return;
547 }
548
549 me_client->props = props_res->client_properties;
550 dev->me_client_index++;
551 dev->me_client_presentation_num++;
552
553 mei_host_client_enumerate(dev);
554
555 break;
556
557 case HOST_ENUM_RES_CMD:
558 enum_res = (struct hbm_host_enum_response *) mei_msg;
559 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
560 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
561 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
562 dev->init_clients_timer = 0;
563 dev->me_client_presentation_num = 0;
564 dev->me_client_index = 0;
565 mei_allocate_me_clients_storage(dev);
566 dev->init_clients_state =
567 MEI_CLIENT_PROPERTIES_MESSAGE;
568
569 mei_host_client_enumerate(dev);
570 } else {
571 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
572 mei_reset(dev, 1);
573 return;
574 }
575 break;
576
577 case HOST_STOP_RES_CMD:
578 dev->dev_state = MEI_DEV_DISABLED;
579 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
580 mei_reset(dev, 1);
581 break;
582
583 case CLIENT_DISCONNECT_REQ_CMD:
584 /* search for client */
585 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
586 mei_client_disconnect_request(dev, disconnect_req);
587 break;
588
589 case ME_STOP_REQ_CMD:
590 {
591 /* prepare stop request: sent in next interrupt event */
592
593 const size_t len = sizeof(struct hbm_host_stop_request);
594
595 hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
596 stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
597 memset(stop_req, 0, len);
598 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
599 stop_req->reason = DRIVER_STOP_REQUEST;
600 break;
601 }
602 default:
603 BUG();
604 break;
605
606 }
607}
608
609 384
610/** 385/**
611 * _mei_hb_read - processes read related operation. 386 * _mei_hb_read - processes read related operation.
@@ -806,7 +581,7 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
806 /* decide where to read the message too */ 581 /* decide where to read the message too */
807 if (!mei_hdr->host_addr) { 582 if (!mei_hdr->host_addr) {
808 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); 583 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
809 mei_irq_thread_read_bus_message(dev, mei_hdr); 584 mei_hbm_dispatch(dev, mei_hdr);
810 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 585 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
811 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 586 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
812 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 587 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&