diff options
Diffstat (limited to 'drivers/misc/mei/hbm.c')
-rw-r--r-- | drivers/misc/mei/hbm.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index de7f5ba3194..4de80d9b7c4 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -123,12 +123,33 @@ static bool is_treat_specially_client(struct mei_cl *cl, return false; } +int mei_hbm_start_wait(struct mei_device *dev) +{ + int ret; + if (dev->hbm_state > MEI_HBM_START) + return 0; + + mutex_unlock(&dev->device_lock); + ret = wait_event_interruptible_timeout(dev->wait_recvd_msg, + dev->hbm_state == MEI_HBM_IDLE || + dev->hbm_state > MEI_HBM_START, + mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); + mutex_lock(&dev->device_lock); + + if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) { + dev->hbm_state = MEI_HBM_IDLE; + dev_err(&dev->pdev->dev, "wating for mei start failed\n"); + return -ETIMEDOUT; + } + return 0; +} + /** * mei_hbm_start_req - sends start request message. * * @dev: the device structure */ -void mei_hbm_start_req(struct mei_device *dev) +int mei_hbm_start_req(struct mei_device *dev) { struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; struct hbm_host_version_request *start_req; @@ -143,18 +164,19 @@ void mei_hbm_start_req(struct mei_device *dev) start_req->host_version.major_version = HBM_MAJOR_VERSION; start_req->host_version.minor_version = HBM_MINOR_VERSION; - dev->recvd_msg = false; + dev->hbm_state = MEI_HBM_IDLE; if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { dev_err(&dev->pdev->dev, "version message writet failed\n"); dev->dev_state = MEI_DEV_RESETING; mei_reset(dev, 1); + return -ENODEV; } - dev->init_clients_state = MEI_START_MESSAGE; + dev->hbm_state = MEI_HBM_START; dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; - return ; + return 0; } -/** +/* * mei_hbm_enum_clients_req - sends enumeration client request message. * * @dev: the device structure @@ -178,7 +200,7 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev) dev_err(&dev->pdev->dev, "enumeration request write failed.\n"); mei_reset(dev, 1); } - dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; + dev->hbm_state = MEI_HBM_ENUM_CLIENTS; dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; return; } @@ -208,6 +230,7 @@ static int mei_hbm_prop_req(struct mei_device *dev) /* We got all client properties */ if (next_client_index == MEI_CLIENTS_MAX) { + dev->hbm_state = MEI_HBM_STARTED; schedule_work(&dev->init_work); return 0; @@ -542,27 +565,28 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) dev->version = version_res->me_max_version; dev_dbg(&dev->pdev->dev, "version mismatch.\n"); + dev->hbm_state = MEI_HBM_STOP; mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, dev->wr_msg.data); mei_write_message(dev, &dev->wr_msg.hdr, dev->wr_msg.data); + return; } dev->version.major_version = HBM_MAJOR_VERSION; dev->version.minor_version = HBM_MINOR_VERSION; if (dev->dev_state == MEI_DEV_INIT_CLIENTS && - dev->init_clients_state == MEI_START_MESSAGE) { + dev->hbm_state == MEI_HBM_START) { dev->init_clients_timer = 0; mei_hbm_enum_clients_req(dev); } else { - dev->recvd_msg = false; dev_err(&dev->pdev->dev, "reset: wrong host start response\n"); mei_reset(dev, 1); return; } - dev->recvd_msg = true; + wake_up_interruptible(&dev->wait_recvd_msg); dev_dbg(&dev->pdev->dev, "host start response message received.\n"); break; @@ -603,7 +627,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) } if (dev->dev_state != MEI_DEV_INIT_CLIENTS || - dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { + dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) { dev_err(&dev->pdev->dev, "reset: unexpected properties response\n"); mei_reset(dev, 1); @@ -623,13 +647,12 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) enum_res = (struct hbm_host_enum_response *) mei_msg; memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); if (dev->dev_state == MEI_DEV_INIT_CLIENTS && - dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { + dev->hbm_state == MEI_HBM_ENUM_CLIENTS) { dev->init_clients_timer = 0; dev->me_client_presentation_num = 0; dev->me_client_index = 0; mei_hbm_me_cl_allocate(dev); - dev->init_clients_state = - MEI_CLIENT_PROPERTIES_MESSAGE; + dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES; /* first property reqeust */ mei_hbm_prop_req(dev); @@ -641,6 +664,9 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) break; case HOST_STOP_RES_CMD: + + if (dev->hbm_state != MEI_HBM_STOP) + dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n"); dev->dev_state = MEI_DEV_DISABLED; dev_info(&dev->pdev->dev, "reset: FW stop response.\n"); mei_reset(dev, 1); @@ -654,6 +680,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) case ME_STOP_REQ_CMD: + dev->hbm_state = MEI_HBM_STOP; mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, dev->wr_ext_msg.data); break; |