diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-18 08:13:20 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-21 15:43:58 -0500 |
commit | c1174c0edf546805a0ebc10d5d6154edbb56e1cf (patch) | |
tree | f1cc9084b89fa8965db5759d84e3094967575b3a /drivers/misc/mei | |
parent | be9d87a790765bcc85d8bdab8a9be31cf7457b28 (diff) |
mei: Simplify the ME client enumeration code
After enumerating all ME clients we call the client init functions for
all matching UUIDs from a separate context.
This remove the hackish cascading client initialisation process that was
interleaving properties and connection command replies.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/init.c | 99 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 75 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 5 |
4 files changed, 95 insertions, 86 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 49600d6e3726..a54cd5567ca2 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -423,54 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) | |||
423 | dev->me_clients = clients; | 423 | dev->me_clients = clients; |
424 | return ; | 424 | return ; |
425 | } | 425 | } |
426 | /** | 426 | |
427 | * host_client_properties - reads properties for client | 427 | void mei_host_client_init(struct work_struct *work) |
428 | * | 428 | { |
429 | * @dev: the device structure | 429 | struct mei_device *dev = container_of(work, |
430 | * | 430 | struct mei_device, init_work); |
431 | * returns: | 431 | struct mei_client_properties *client_props; |
432 | * < 0 - Error. | 432 | int i; |
433 | * = 0 - no more clients. | 433 | |
434 | * = 1 - still have clients to send properties request. | 434 | mutex_lock(&dev->device_lock); |
435 | */ | 435 | |
436 | int mei_host_client_properties(struct mei_device *dev) | 436 | bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); |
437 | dev->open_handle_count = 0; | ||
438 | |||
439 | /* | ||
440 | * Reserving the first three client IDs | ||
441 | * 0: Reserved for MEI Bus Message communications | ||
442 | * 1: Reserved for Watchdog | ||
443 | * 2: Reserved for AMTHI | ||
444 | */ | ||
445 | bitmap_set(dev->host_clients_map, 0, 3); | ||
446 | |||
447 | for (i = 0; i < dev->me_clients_num; i++) { | ||
448 | client_props = &dev->me_clients[i].props; | ||
449 | |||
450 | if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) | ||
451 | mei_amthif_host_init(dev); | ||
452 | else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) | ||
453 | mei_wd_host_init(dev); | ||
454 | } | ||
455 | |||
456 | dev->dev_state = MEI_DEV_ENABLED; | ||
457 | |||
458 | mutex_unlock(&dev->device_lock); | ||
459 | } | ||
460 | |||
461 | int mei_host_client_enumerate(struct mei_device *dev) | ||
437 | { | 462 | { |
438 | 463 | ||
439 | struct mei_msg_hdr *mei_hdr; | 464 | struct mei_msg_hdr *mei_hdr; |
440 | struct hbm_props_request *prop_req; | 465 | struct hbm_props_request *prop_req; |
441 | const size_t len = sizeof(struct hbm_props_request); | 466 | const size_t len = sizeof(struct hbm_props_request); |
467 | unsigned long next_client_index; | ||
468 | u8 client_num; | ||
442 | 469 | ||
443 | int b; | ||
444 | u8 client_num = dev->me_client_presentation_num; | ||
445 | 470 | ||
446 | prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | 471 | client_num = dev->me_client_presentation_num; |
447 | 472 | ||
448 | b = dev->me_client_index; | 473 | next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, |
449 | b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b); | 474 | dev->me_client_index); |
450 | if (b < MEI_CLIENTS_MAX) { | ||
451 | dev->me_clients[client_num].client_id = b; | ||
452 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; | ||
453 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
454 | 475 | ||
476 | /* We got all client properties */ | ||
477 | if (next_client_index == MEI_CLIENTS_MAX) { | ||
478 | schedule_work(&dev->init_work); | ||
455 | 479 | ||
456 | memset(prop_req, 0, sizeof(struct hbm_props_request)); | 480 | return 0; |
481 | } | ||
457 | 482 | ||
458 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | 483 | dev->me_clients[client_num].client_id = next_client_index; |
459 | prop_req->address = b; | 484 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; |
485 | |||
486 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
487 | prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | ||
488 | |||
489 | memset(prop_req, 0, sizeof(struct hbm_props_request)); | ||
460 | 490 | ||
461 | if (mei_write_message(dev, mei_hdr, | ||
462 | (unsigned char *)prop_req, len)) { | ||
463 | dev->dev_state = MEI_DEV_RESETING; | ||
464 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | ||
465 | mei_reset(dev, 1); | ||
466 | return -EIO; | ||
467 | } | ||
468 | 491 | ||
469 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | 492 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; |
470 | dev->me_client_index = b; | 493 | prop_req->address = next_client_index; |
471 | return 1; | 494 | |
495 | if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req, | ||
496 | mei_hdr->length)) { | ||
497 | dev->dev_state = MEI_DEV_RESETING; | ||
498 | dev_err(&dev->pdev->dev, "Properties request command failed\n"); | ||
499 | mei_reset(dev, 1); | ||
500 | |||
501 | return -EIO; | ||
472 | } | 502 | } |
473 | 503 | ||
504 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | ||
505 | dev->me_client_index = next_client_index; | ||
506 | |||
474 | return 0; | 507 | return 0; |
475 | } | 508 | } |
476 | 509 | ||
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index e5aa0ed3b8eb..04fa2134615e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -252,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev, | |||
252 | dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); | 252 | dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); |
253 | mei_watchdog_register(dev); | 253 | mei_watchdog_register(dev); |
254 | 254 | ||
255 | /* next step in the state maching */ | ||
256 | mei_amthif_host_init(dev); | ||
257 | return; | 255 | return; |
258 | } | 256 | } |
259 | 257 | ||
@@ -470,6 +468,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
470 | struct mei_msg_hdr *mei_hdr) | 468 | struct mei_msg_hdr *mei_hdr) |
471 | { | 469 | { |
472 | struct mei_bus_message *mei_msg; | 470 | struct mei_bus_message *mei_msg; |
471 | struct mei_me_client *me_client; | ||
473 | struct hbm_host_version_response *version_res; | 472 | struct hbm_host_version_response *version_res; |
474 | struct hbm_client_connect_response *connect_res; | 473 | struct hbm_client_connect_response *connect_res; |
475 | struct hbm_client_connect_response *disconnect_res; | 474 | struct hbm_client_connect_response *disconnect_res; |
@@ -478,8 +477,6 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
478 | struct hbm_props_response *props_res; | 477 | struct hbm_props_response *props_res; |
479 | struct hbm_host_enum_response *enum_res; | 478 | struct hbm_host_enum_response *enum_res; |
480 | struct hbm_host_stop_request *stop_req; | 479 | struct hbm_host_stop_request *stop_req; |
481 | int res; | ||
482 | |||
483 | 480 | ||
484 | /* read the message to our buffer */ | 481 | /* read the message to our buffer */ |
485 | BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); | 482 | BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); |
@@ -547,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
547 | 544 | ||
548 | case HOST_CLIENT_PROPERTIES_RES_CMD: | 545 | case HOST_CLIENT_PROPERTIES_RES_CMD: |
549 | props_res = (struct hbm_props_response *)mei_msg; | 546 | props_res = (struct hbm_props_response *)mei_msg; |
547 | me_client = &dev->me_clients[dev->me_client_presentation_num]; | ||
548 | |||
550 | if (props_res->status || !dev->me_clients) { | 549 | if (props_res->status || !dev->me_clients) { |
551 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); | 550 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); |
552 | mei_reset(dev, 1); | 551 | mei_reset(dev, 1); |
553 | return; | 552 | return; |
554 | } | 553 | } |
555 | if (dev->me_clients[dev->me_client_presentation_num] | ||
556 | .client_id == props_res->address) { | ||
557 | 554 | ||
558 | dev->me_clients[dev->me_client_presentation_num].props | 555 | if (me_client->client_id != props_res->address) { |
559 | = props_res->client_properties; | 556 | dev_err(&dev->pdev->dev, |
557 | "Host client properties reply mismatch\n"); | ||
558 | mei_reset(dev, 1); | ||
560 | 559 | ||
561 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && | 560 | return; |
562 | dev->init_clients_state == | 561 | } |
563 | MEI_CLIENT_PROPERTIES_MESSAGE) { | ||
564 | dev->me_client_index++; | ||
565 | dev->me_client_presentation_num++; | ||
566 | |||
567 | /** Send Client Properties request **/ | ||
568 | res = mei_host_client_properties(dev); | ||
569 | if (res < 0) { | ||
570 | dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed"); | ||
571 | return; | ||
572 | } else if (!res) { | ||
573 | /* | ||
574 | * No more clients to send to. | ||
575 | * Clear Map for indicating now ME clients | ||
576 | * with associated host client | ||
577 | */ | ||
578 | bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); | ||
579 | dev->open_handle_count = 0; | ||
580 | |||
581 | /* | ||
582 | * Reserving the first three client IDs | ||
583 | * Client Id 0 - Reserved for MEI Bus Message communications | ||
584 | * Client Id 1 - Reserved for Watchdog | ||
585 | * Client ID 2 - Reserved for AMTHI | ||
586 | */ | ||
587 | bitmap_set(dev->host_clients_map, 0, 3); | ||
588 | dev->dev_state = MEI_DEV_ENABLED; | ||
589 | |||
590 | /* if wd initialization fails, initialization the AMTHI client, | ||
591 | * otherwise the AMTHI client will be initialized after the WD client connect response | ||
592 | * will be received | ||
593 | */ | ||
594 | if (mei_wd_host_init(dev)) | ||
595 | mei_amthif_host_init(dev); | ||
596 | } | ||
597 | 562 | ||
598 | } else { | 563 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || |
599 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message"); | 564 | dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { |
600 | mei_reset(dev, 1); | 565 | dev_err(&dev->pdev->dev, |
601 | return; | 566 | "Unexpected client properties reply\n"); |
602 | } | ||
603 | } else { | ||
604 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n"); | ||
605 | mei_reset(dev, 1); | 567 | mei_reset(dev, 1); |
568 | |||
606 | return; | 569 | return; |
607 | } | 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 | |||
608 | break; | 578 | break; |
609 | 579 | ||
610 | case HOST_ENUM_RES_CMD: | 580 | case HOST_ENUM_RES_CMD: |
@@ -618,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
618 | mei_allocate_me_clients_storage(dev); | 588 | mei_allocate_me_clients_storage(dev); |
619 | dev->init_clients_state = | 589 | dev->init_clients_state = |
620 | MEI_CLIENT_PROPERTIES_MESSAGE; | 590 | MEI_CLIENT_PROPERTIES_MESSAGE; |
621 | mei_host_client_properties(dev); | 591 | |
592 | mei_host_client_enumerate(dev); | ||
622 | } else { | 593 | } else { |
623 | dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); | 594 | dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); |
624 | mei_reset(dev, 1); | 595 | mei_reset(dev, 1); |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 251aafff5492..7c9c381e5c9a 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -829,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev, | |||
829 | goto disable_msi; | 829 | goto disable_msi; |
830 | } | 830 | } |
831 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); | 831 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); |
832 | INIT_WORK(&dev->init_work, mei_host_client_init); | ||
833 | |||
832 | if (mei_hw_init(dev)) { | 834 | if (mei_hw_init(dev)) { |
833 | dev_err(&pdev->dev, "init hw failure.\n"); | 835 | dev_err(&pdev->dev, "init hw failure.\n"); |
834 | err = -ENODEV; | 836 | err = -ENODEV; |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 17d00aae74e6..25da04549d04 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -287,6 +287,8 @@ struct mei_device { | |||
287 | bool iamthif_flow_control_pending; | 287 | bool iamthif_flow_control_pending; |
288 | bool iamthif_ioctl; | 288 | bool iamthif_ioctl; |
289 | bool iamthif_canceled; | 289 | bool iamthif_canceled; |
290 | |||
291 | struct work_struct init_work; | ||
290 | }; | 292 | }; |
291 | 293 | ||
292 | static inline unsigned long mei_secs_to_jiffies(unsigned long sec) | 294 | static inline unsigned long mei_secs_to_jiffies(unsigned long sec) |
@@ -363,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1, | |||
363 | */ | 365 | */ |
364 | void mei_host_start_message(struct mei_device *dev); | 366 | void mei_host_start_message(struct mei_device *dev); |
365 | void mei_host_enum_clients_message(struct mei_device *dev); | 367 | void mei_host_enum_clients_message(struct mei_device *dev); |
366 | int mei_host_client_properties(struct mei_device *dev); | 368 | int mei_host_client_enumerate(struct mei_device *dev); |
369 | void mei_host_client_init(struct work_struct *work); | ||
367 | 370 | ||
368 | /* | 371 | /* |
369 | * MEI interrupt functions prototype | 372 | * MEI interrupt functions prototype |