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: Zhen Kong <zkong@codeaurora.org>
This commit is contained in:
parent
b3ba6ffa2c
commit
4aa1034bf7
1 changed files with 71 additions and 129 deletions
|
@ -1845,7 +1845,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)
|
||||
|
@ -1854,10 +1854,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");
|
||||
|
@ -1888,140 +1889,81 @@ static int __qseecom_process_blocked_on_listener_legacy(
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ptr_app->blocked_on_listener_id = resp->data;
|
||||
|
||||
/* sleep until listener is available */
|
||||
sigfillset(&new_sigset);
|
||||
sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
|
||||
|
||||
do {
|
||||
qseecom.app_block_ref_cnt++;
|
||||
ptr_app->app_blocked = true;
|
||||
mutex_unlock(&app_access_lock);
|
||||
wait_event_freezable(
|
||||
list_ptr->listener_block_app_wq,
|
||||
!list_ptr->listener_in_use);
|
||||
mutex_lock(&app_access_lock);
|
||||
ptr_app->app_blocked = false;
|
||||
qseecom.app_block_ref_cnt--;
|
||||
} while (list_ptr->listener_in_use);
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
ireq.app_or_session_id = session_id;
|
||||
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
|
||||
&ireq, sizeof(ireq),
|
||||
&continue_resp, sizeof(continue_resp));
|
||||
if (ret) {
|
||||
/* retry with legacy cmd */
|
||||
qseecom.smcinvoke_support = false;
|
||||
ireq.app_or_session_id = 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);
|
||||
session_id = resp->resp_type;
|
||||
list_ptr = __qseecom_find_svc(resp->data);
|
||||
if (!list_ptr) {
|
||||
pr_err("Invalid listener ID %d\n", resp->data);
|
||||
ret = -ENODATA;
|
||||
goto exit;
|
||||
}
|
||||
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);
|
||||
|
||||
do {
|
||||
qseecom.app_block_ref_cnt++;
|
||||
ptr_app->app_blocked = true;
|
||||
mutex_unlock(&app_access_lock);
|
||||
wait_event_freezable(
|
||||
list_ptr->listener_block_app_wq,
|
||||
!list_ptr->listener_in_use);
|
||||
mutex_lock(&app_access_lock);
|
||||
ptr_app->app_blocked = false;
|
||||
qseecom.app_block_ref_cnt--;
|
||||
} while (list_ptr->listener_in_use);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &old_sigset, NULL);
|
||||
|
||||
ptr_app->blocked_on_listener_id = 0;
|
||||
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 */
|
||||
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 && qseecom.smcinvoke_support) {
|
||||
/* retry with legacy cmd */
|
||||
qseecom.smcinvoke_support = false;
|
||||
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("unblock app %d or session %d fail\n",
|
||||
data->client.app_id, session_id);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
resp->result = QSEOS_RESULT_INCOMPLETE;
|
||||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue