diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c index bbfe6a4b92b8..8165a8cd633a 100644 --- a/drivers/soc/qcom/smcinvoke.c +++ b/drivers/soc/qcom/smcinvoke.c @@ -61,6 +61,7 @@ */ #define SMCINVOKE_SERVER_STATE_DEFUNCT 1 +#define CBOBJ_MAX_RETRIES 5 #define FOR_ARGS(ndxvar, counts, section) \ for (ndxvar = OBJECT_COUNTS_INDEX_##section(counts); \ ndxvar < (OBJECT_COUNTS_INDEX_##section(counts) \ @@ -1002,6 +1003,8 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) { /* ret is going to TZ. Provide values from OBJECT_ERROR_<> */ int ret = OBJECT_ERROR_DEFUNCT; + int cbobj_retries = 0; + long timeout_jiff; struct smcinvoke_cb_txn *cb_txn = NULL; struct smcinvoke_tzcb_req *cb_req = NULL, *tmp_cb_req = NULL; struct smcinvoke_server_info *srvr_info = NULL; @@ -1079,9 +1082,26 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) * as this CBObj is served by this server, srvr_info will be valid. */ wake_up_interruptible_all(&srvr_info->req_wait_q); - ret = wait_event_interruptible(srvr_info->rsp_wait_q, - (cb_txn->state == SMCINVOKE_REQ_PROCESSED) || - (srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT)); + /* timeout before 1s otherwise tzbusy would come */ + timeout_jiff = msecs_to_jiffies(1000); + + while (cbobj_retries < CBOBJ_MAX_RETRIES) { + ret = wait_event_interruptible_timeout(srvr_info->rsp_wait_q, + (cb_txn->state == SMCINVOKE_REQ_PROCESSED) || + (srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT), + timeout_jiff); + + if (ret == 0) { + pr_err("CBobj timed out cb-tzhandle:%d, retry:%d, op:%d counts :%d\n", + cb_req->hdr.tzhandle, cbobj_retries, cb_req->hdr.op, cb_req->hdr.counts); + pr_err("CBobj %d timedout pid %x,tid %x, srvr state=%d, srvr id:%u\n", + cb_req->hdr.tzhandle, current->pid, current->tgid, srvr_info->state, + srvr_info->server_id); + } else { + break; + } + cbobj_retries++; + } out: /* @@ -1091,18 +1111,26 @@ out: */ mutex_lock(&g_smcinvoke_lock); hash_del(&cb_txn->hash); - if (cb_txn->state == SMCINVOKE_REQ_PROCESSED) { - /* - * it is possible that server was killed immediately - * after CB Req was processed but who cares now! - */ - } else if (!srvr_info || - srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT) { - cb_req->result = OBJECT_ERROR_DEFUNCT; - pr_err("server invalid, res: %d\n", cb_req->result); - } else { - pr_debug("%s wait_event interrupted ret = %d\n", __func__, ret); + if (ret == 0) { + pr_err("CBObj timed out! No more retries\n"); cb_req->result = OBJECT_ERROR_ABORT; + } else if (ret < 0) { + pr_err("wait event interruped, ret: %d\n", ret); + cb_req->result = OBJECT_ERROR_ABORT; + } else { + if (cb_txn->state == SMCINVOKE_REQ_PROCESSED) { + /* + * it is possible that server was killed immediately + * after CB Req was processed but who cares now! + */ + } else if (!srvr_info || + srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT) { + cb_req->result = OBJECT_ERROR_DEFUNCT; + pr_err("server invalid, res: %d\n", cb_req->result); + } else { + pr_err("%s: unexpected event happened\n", __func__); + cb_req->result = OBJECT_ERROR_ABORT; + } } --cb_reqs_inflight; memcpy(buf, cb_req, buf_len);