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

Commit 1f74d8ce authored by Zhen Kong's avatar Zhen Kong Committed by Gerrit - the friendly Code Review server
Browse files

qseecom: fix issues when processing blocked listener request



When processing blocked listener request, ptr_app's app_blocked
flag should be set to prevent it being unloaded at this time;
Besides, need to check unblock request's scm_call response result
to see if it is blocked again; and removed redundant codes.

Change-Id: I2d72a88e9e600d6b7e944ae978b9d89a7b6db242
Signed-off-by: default avatarZhen Kong <zkong@codeaurora.org>
parent d4e49c00
Loading
Loading
Loading
Loading
+63 −121
Original line number Diff line number Diff line
@@ -1843,7 +1843,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
	return ret;
}

static int __qseecom_process_blocked_on_listener_legacy(
static int __qseecom_process_reentrancy_blocked_on_listener(
				struct qseecom_command_scm_resp *resp,
				struct qseecom_registered_app_list *ptr_app,
				struct qseecom_dev_handle *data)
@@ -1852,10 +1852,11 @@ static int __qseecom_process_blocked_on_listener_legacy(
	int ret = 0;
	struct qseecom_continue_blocked_request_ireq ireq;
	struct qseecom_command_scm_resp continue_resp;
	bool found_app = false;
	unsigned long flags;
	unsigned int session_id;
	sigset_t new_sigset;
	sigset_t old_sigset;
	unsigned long flags;
	bool found_app = false;

	if (!resp || !data) {
		pr_err("invalid resp or data pointer\n");
@@ -1886,16 +1887,20 @@ static int __qseecom_process_blocked_on_listener_legacy(
		}
	}

	do {
		session_id = resp->resp_type;
		list_ptr = __qseecom_find_svc(resp->data);
		if (!list_ptr) {
		pr_err("Invalid listener ID\n");
			pr_err("Invalid listener ID %d\n", resp->data);
			ret = -ENODATA;
			goto exit;
		}
	pr_debug("lsntr %d in_use = %d\n",
			resp->data, list_ptr->listener_in_use);
		ptr_app->blocked_on_listener_id = resp->data;

		pr_warn("Lsntr %d in_use %d, block session(%d) app(%d)\n",
			resp->data, list_ptr->listener_in_use,
			session_id, data->client.app_id);

		/* sleep until listener is available */
		sigfillset(&new_sigset);
		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
@@ -1915,111 +1920,48 @@ static int __qseecom_process_blocked_on_listener_legacy(
		sigprocmask(SIG_SETMASK, &old_sigset, NULL);

		ptr_app->blocked_on_listener_id = 0;
	/* notify the blocked app that listener is available */
	pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n",
		resp->data, data->client.app_id,
		data->client.app_name);
	ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND;
	ireq.app_or_session_id = data->client.app_id;
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
			&ireq, sizeof(ireq),
			&continue_resp, sizeof(continue_resp));
	if (ret) {
		pr_err("scm_call for continue blocked req for app(%d) %s failed, ret %d\n",
			data->client.app_id,
			data->client.app_name, ret);
		goto exit;
	}
	/*
	 * After TZ app is unblocked, then continue to next case
	 * for incomplete request processing
	 */
	resp->result = QSEOS_RESULT_INCOMPLETE;
exit:
	return ret;
}

static int __qseecom_process_blocked_on_listener_smcinvoke(
			struct qseecom_command_scm_resp *resp, uint32_t app_id)
{
	struct qseecom_registered_listener_list *list_ptr;
	int ret = 0;
	struct qseecom_continue_blocked_request_ireq ireq;
	struct qseecom_command_scm_resp continue_resp;
	unsigned int session_id;
	sigset_t new_sigset;
	sigset_t old_sigset;

	if (!resp) {
		pr_err("invalid resp pointer\n");
		ret = -EINVAL;
		goto exit;
	}
	session_id = resp->resp_type;
	list_ptr = __qseecom_find_svc(resp->data);
	if (!list_ptr) {
		pr_err("Invalid listener ID\n");
		ret = -ENODATA;
		goto exit;
	}
	pr_debug("lsntr %d in_use = %d\n",
			resp->data, list_ptr->listener_in_use);

	/* sleep until listener is available */
	sigfillset(&new_sigset);
	sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);

	do {
		qseecom.app_block_ref_cnt++;
		mutex_unlock(&app_access_lock);
		wait_event_freezable(
			list_ptr->listener_block_app_wq,
			!list_ptr->listener_in_use);
		mutex_lock(&app_access_lock);
		qseecom.app_block_ref_cnt--;
	}  while (list_ptr->listener_in_use);

	sigprocmask(SIG_SETMASK, &old_sigset, NULL);
		pr_warn("Lsntr %d is available, unblock session(%d) app(%d)\n",
			resp->data, session_id, data->client.app_id);

		/* notify TZ that listener is available */
	pr_warn("Lsntr %d is available, unblock session(%d) in TZ\n",
			resp->data, session_id);
		ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND;

		if (qseecom.smcinvoke_support)
			ireq.app_or_session_id = session_id;
		else
			ireq.app_or_session_id = data->client.app_id;

		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
					&ireq, sizeof(ireq),
					&continue_resp, sizeof(continue_resp));
	if (ret) {
		if (ret && qseecom.smcinvoke_support) {
			/* retry with legacy cmd */
			qseecom.smcinvoke_support = false;
		ireq.app_or_session_id = app_id;
			ireq.app_or_session_id = data->client.app_id;
			ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
				&ireq, sizeof(ireq),
				&continue_resp, sizeof(continue_resp));
			qseecom.smcinvoke_support = true;
			if (ret) {
			pr_err("cont block req for app %d or session %d fail\n",
				app_id, session_id);
				pr_err("unblock app %d or session %d fail\n",
					data->client.app_id, session_id);
				goto exit;
			}
		}
	resp->result = QSEOS_RESULT_INCOMPLETE;
		resp->result = continue_resp.result;
		resp->resp_type = continue_resp.resp_type;
		resp->data = continue_resp.data;
		pr_debug("unblock resp = %d\n", resp->result);
	} while (resp->result == QSEOS_RESULT_BLOCKED_ON_LISTENER);

	if (resp->result != QSEOS_RESULT_INCOMPLETE) {
		pr_err("Unexpected unblock resp %d\n", resp->result);
		ret = -EINVAL;
	}
exit:
	return ret;
}

static int __qseecom_process_reentrancy_blocked_on_listener(
				struct qseecom_command_scm_resp *resp,
				struct qseecom_registered_app_list *ptr_app,
				struct qseecom_dev_handle *data)
{
	if (!qseecom.smcinvoke_support)
		return __qseecom_process_blocked_on_listener_legacy(
			resp, ptr_app, data);
	else
		return __qseecom_process_blocked_on_listener_smcinvoke(
			resp, data->client.app_id);
}
static int __qseecom_reentrancy_process_incomplete_cmd(
					struct qseecom_dev_handle *data,
					struct qseecom_command_scm_resp *resp)