Loading drivers/misc/qseecom.c +72 −113 Original line number Diff line number Diff line /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -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) Loading @@ -1852,8 +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 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 @@ -1884,128 +1887,81 @@ 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); do { qseecom.app_block_ref_cnt++; ptr_app->app_blocked = true; mutex_unlock(&app_access_lock); if (wait_event_freezable( wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, app_id %d\n", resp->data, ptr_app->app_id); ret = -ERESTARTSYS; goto exit; } !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); 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("scm_call for continue blocked req for app(%d) %s failed, ret %d\n", data->client.app_id, data->client.app_name, ret); pr_err("unblock app %d or session %d fail\n", data->client.app_id, session_id); goto exit; } /* * After TZ app is unblocked, then continue to next case * for incomplete request processing */ resp->result = QSEOS_RESULT_INCOMPLETE; exit: return ret; } 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); static int __qseecom_process_blocked_on_listener_smcinvoke( struct qseecom_command_scm_resp *resp) { 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; if (!resp) { pr_err("invalid resp pointer\n"); if (resp->result != QSEOS_RESULT_INCOMPLETE) { pr_err("Unexpected unblock resp %d\n", resp->result); 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 */ do { qseecom.app_block_ref_cnt++; mutex_unlock(&app_access_lock); if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, session_id %d\n", resp->data, session_id); ret = -ERESTARTSYS; goto exit; } mutex_lock(&app_access_lock); qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use); /* 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) { pr_err("scm_call for continue blocked req for session %d failed, ret %d\n", session_id, ret); goto exit; } 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); } static int __qseecom_reentrancy_process_incomplete_cmd( struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) Loading Loading @@ -4782,6 +4738,9 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/ resp.data = desc->ret[2]; /*listener_id*/ dummy_private_data.client.app_id = desc->ret[1]; dummy_app_entry.app_id = desc->ret[1]; mutex_lock(&app_access_lock); if (qseecom.qsee_reentrancy_support) ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry, Loading Loading
drivers/misc/qseecom.c +72 −113 Original line number Diff line number Diff line /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -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) Loading @@ -1852,8 +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 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 @@ -1884,128 +1887,81 @@ 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); do { qseecom.app_block_ref_cnt++; ptr_app->app_blocked = true; mutex_unlock(&app_access_lock); if (wait_event_freezable( wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, app_id %d\n", resp->data, ptr_app->app_id); ret = -ERESTARTSYS; goto exit; } !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); 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("scm_call for continue blocked req for app(%d) %s failed, ret %d\n", data->client.app_id, data->client.app_name, ret); pr_err("unblock app %d or session %d fail\n", data->client.app_id, session_id); goto exit; } /* * After TZ app is unblocked, then continue to next case * for incomplete request processing */ resp->result = QSEOS_RESULT_INCOMPLETE; exit: return ret; } 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); static int __qseecom_process_blocked_on_listener_smcinvoke( struct qseecom_command_scm_resp *resp) { 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; if (!resp) { pr_err("invalid resp pointer\n"); if (resp->result != QSEOS_RESULT_INCOMPLETE) { pr_err("Unexpected unblock resp %d\n", resp->result); 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 */ do { qseecom.app_block_ref_cnt++; mutex_unlock(&app_access_lock); if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, session_id %d\n", resp->data, session_id); ret = -ERESTARTSYS; goto exit; } mutex_lock(&app_access_lock); qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use); /* 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) { pr_err("scm_call for continue blocked req for session %d failed, ret %d\n", session_id, ret); goto exit; } 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); } static int __qseecom_reentrancy_process_incomplete_cmd( struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) Loading Loading @@ -4782,6 +4738,9 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/ resp.data = desc->ret[2]; /*listener_id*/ dummy_private_data.client.app_id = desc->ret[1]; dummy_app_entry.app_id = desc->ret[1]; mutex_lock(&app_access_lock); if (qseecom.qsee_reentrancy_support) ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry, Loading