Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e55be430 authored by Anmolpreet Kaur's avatar Anmolpreet Kaur
Browse files

smcinvoke: implement retry and timeout for CB processing



CB requests are processed by HLOS userspace. It is possible that
userspace never returns with a response. This could cause trusted
environment that initiated CB request to reject processing anymore
non-secure requests. This is not a desirable situation. Hence, adding
timeout functionality along with retry mechanism to send error response
back to trusted env after maximum number of retries are already done and
continue processing requests from non-secure side.

Change-Id: Idbd3048d0b9594c9927d55a24a8ca77e14214746
Signed-off-by: default avatarAnmolpreet Kaur <anmolpre@codeaurora.org>
parent aa860b5b
Loading
Loading
Loading
Loading
+42 −14
Original line number Diff line number Diff line
@@ -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,
	/* 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));
			(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,6 +1111,13 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
	 */
	mutex_lock(&g_smcinvoke_lock);
	hash_del(&cb_txn->hash);
	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
@@ -1101,9 +1128,10 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
			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);
			pr_err("%s: unexpected event happened\n", __func__);
			cb_req->result = OBJECT_ERROR_ABORT;
		}
	}
	--cb_reqs_inflight;
	memcpy(buf, cb_req, buf_len);
	kref_put(&cb_txn->ref_cnt, delete_cb_txn);