diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 3b5c3059a02d..ce47780e5936 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -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)