diff options
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r-- | drivers/misc/mei/init.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 49600d6..a54cd55 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) dev->me_clients = clients; return ; } -/** - * host_client_properties - reads properties for client - * - * @dev: the device structure - * - * returns: - * < 0 - Error. - * = 0 - no more clients. - * = 1 - still have clients to send properties request. - */ -int mei_host_client_properties(struct mei_device *dev) + +void mei_host_client_init(struct work_struct *work) +{ + struct mei_device *dev = container_of(work, + struct mei_device, init_work); + struct mei_client_properties *client_props; + int i; + + mutex_lock(&dev->device_lock); + + bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); + dev->open_handle_count = 0; + + /* + * Reserving the first three client IDs + * 0: Reserved for MEI Bus Message communications + * 1: Reserved for Watchdog + * 2: Reserved for AMTHI + */ + bitmap_set(dev->host_clients_map, 0, 3); + + for (i = 0; i < dev->me_clients_num; i++) { + client_props = &dev->me_clients[i].props; + + if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) + mei_amthif_host_init(dev); + else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) + mei_wd_host_init(dev); + } + + dev->dev_state = MEI_DEV_ENABLED; + + mutex_unlock(&dev->device_lock); +} + +int mei_host_client_enumerate(struct mei_device *dev) { struct mei_msg_hdr *mei_hdr; struct hbm_props_request *prop_req; const size_t len = sizeof(struct hbm_props_request); + unsigned long next_client_index; + u8 client_num; - int b; - u8 client_num = dev->me_client_presentation_num; - prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; + client_num = dev->me_client_presentation_num; - b = dev->me_client_index; - b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b); - if (b < MEI_CLIENTS_MAX) { - dev->me_clients[client_num].client_id = b; - dev->me_clients[client_num].mei_flow_ctrl_creds = 0; - mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); + next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, + dev->me_client_index); + /* We got all client properties */ + if (next_client_index == MEI_CLIENTS_MAX) { + schedule_work(&dev->init_work); - memset(prop_req, 0, sizeof(struct hbm_props_request)); + return 0; + } - prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; - prop_req->address = b; + dev->me_clients[client_num].client_id = next_client_index; + dev->me_clients[client_num].mei_flow_ctrl_creds = 0; + + mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); + prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; + + memset(prop_req, 0, sizeof(struct hbm_props_request)); - if (mei_write_message(dev, mei_hdr, - (unsigned char *)prop_req, len)) { - dev->dev_state = MEI_DEV_RESETING; - dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); - mei_reset(dev, 1); - return -EIO; - } - dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; - dev->me_client_index = b; - return 1; + prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; + prop_req->address = next_client_index; + + if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req, + mei_hdr->length)) { + dev->dev_state = MEI_DEV_RESETING; + dev_err(&dev->pdev->dev, "Properties request command failed\n"); + mei_reset(dev, 1); + + return -EIO; } + dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; + dev->me_client_index = next_client_index; + return 0; } |