Loading drivers/misc/qseecom.c +63 −121 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,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) Loading @@ -1858,10 +1858,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"); Loading Loading @@ -1892,16 +1893,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); Loading @@ -1921,111 +1926,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) Loading Loading
drivers/misc/qseecom.c +63 −121 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,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) Loading @@ -1858,10 +1858,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"); Loading Loading @@ -1892,16 +1893,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); Loading @@ -1921,111 +1926,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) Loading