diff options
Diffstat (limited to 'drivers/misc/mei/interrupt.c')
-rw-r--r-- | drivers/misc/mei/interrupt.c | 235 |
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 | */ |
211 | static void mei_client_connect_response(struct mei_device *dev, | 211 | void 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 | */ |
264 | static void mei_client_disconnect_response(struct mei_device *dev, | 264 | void 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 | */ |
350 | static void mei_client_flow_control_response(struct mei_device *dev, | 350 | void 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 | */ | ||
392 | static 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 | */ | ||
405 | static 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 | */ | ||
445 | static 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) && |