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

Commit 8168d364 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "smcinvoke: implement retry and timeout for CB processing"

parents 669adc0e e55be430
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);