aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhen Kong <zkong@codeaurora.org>2019-02-01 17:12:34 -0800
committerCraft Ju <craftju@google.com>2019-05-29 06:25:41 +0000
commit9d5eb1007a48afe7e3f4d6639d2acaba832c17dc (patch)
tree8057ad169ca30516b9d3d6b8c4c94dd7017127d4
parent1e879971590684f818b3926f1af4a6417a3576b3 (diff)
qseecom: replace scm_call2 with scm_call2_noretry
To avoid potential EBUSY error from scm_call2() when smcinvoke TA requests listener and qseecom sends scm_call at the same time, change to use scm_call2_noretry and release app_access_mutex before msleep. Bug: 133120616 Bug: 133128687 Change-Id: I57103d3f5667df6ced824e51ba6555f5d6722af3 Signed-off-by: Zhen Kong <zkong@codeaurora.org>
-rw-r--r--drivers/misc/qseecom.c91
1 files changed, 59 insertions, 32 deletions
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index e1edf50cb4c0..15f8f6f2d107 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -412,6 +412,29 @@ static int get_qseecom_keymaster_status(char *str)
}
__setup("androidboot.keymaster=", get_qseecom_keymaster_status);
+
+#define QSEECOM_SCM_EBUSY_WAIT_MS 30
+#define QSEECOM_SCM_EBUSY_MAX_RETRY 67
+
+static int __qseecom_scm_call2_locked(uint32_t smc_id, struct scm_desc *desc)
+{
+ int ret = 0;
+ int retry_count = 0;
+
+ do {
+ ret = scm_call2_noretry(smc_id, desc);
+ if (ret == -EBUSY) {
+ mutex_unlock(&app_access_lock);
+ msleep(QSEECOM_SCM_EBUSY_WAIT_MS);
+ mutex_lock(&app_access_lock);
+ }
+ if (retry_count == 33)
+ pr_warn("secure world has been busy for 1 second!\n");
+ } while (ret == -EBUSY &&
+ (retry_count++ < QSEECOM_SCM_EBUSY_MAX_RETRY));
+ return ret;
+}
+
static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
const void *req_buf, void *resp_buf)
{
@@ -439,7 +462,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
svc_id, tz_cmd_id);
return -EINVAL;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case SCM_SVC_ES: {
@@ -462,7 +485,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = p_hash_req->partition_id;
desc.args[1] = virt_to_phys(tzbuf);
desc.args[2] = SHA256_DIGEST_LENGTH;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -497,7 +520,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_APP_SHUTDOWN_COMMAND: {
@@ -507,7 +530,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
smc_id = TZ_OS_APP_SHUTDOWN_ID;
desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
desc.args[0] = req->app_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_APP_LOOKUP_COMMAND: {
@@ -526,7 +549,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = strlen(req->app_name);
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -550,7 +573,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[1] = req_64bit->size;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LOAD_SERV_IMAGE_COMMAND: {
@@ -574,14 +597,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_UNLOAD_SERV_IMAGE_COMMAND: {
smc_id = TZ_OS_UNLOAD_SERVICES_IMAGE_ID;
desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_REGISTER_LISTENER: {
@@ -606,12 +629,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
}
qseecom.smcinvoke_support = true;
smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
if (ret == -EIO) {
/* smcinvoke is not supported */
qseecom.smcinvoke_support = false;
smc_id = TZ_OS_REGISTER_LISTENER_ID;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
}
break;
}
@@ -623,7 +646,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
desc.args[0] = req->listener_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LISTENER_DATA_RSP_COMMAND: {
@@ -636,7 +659,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID;
desc.args[0] = req->listener_id;
desc.args[1] = req->status;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: {
@@ -664,7 +687,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64->sglistinfo_ptr;
desc.args[3] = req_64->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: {
@@ -686,14 +709,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND: {
smc_id = TZ_OS_UNLOAD_EXTERNAL_IMAGE_ID;
desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
@@ -721,7 +744,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->rsp_ptr;
desc.args[4] = req_64bit->rsp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: {
@@ -753,7 +776,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_PROVISION_KEY_COMMAND: {
@@ -765,21 +788,21 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.arginfo = TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID;
desc.args[0] = req->key_type;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_ERASE_COMMAND: {
smc_id = TZ_OS_RPMB_ERASE_ID;
desc.arginfo = TZ_OS_RPMB_ERASE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND: {
smc_id = TZ_OS_RPMB_CHECK_PROV_STATUS_ID;
desc.arginfo = TZ_OS_RPMB_CHECK_PROV_STATUS_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_GENERATE_KEY: {
@@ -800,7 +823,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -822,7 +845,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -844,7 +867,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -866,7 +889,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -892,7 +915,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_OPEN_SESSION_WHITELIST: {
@@ -922,7 +945,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_INVOKE_COMMAND: {
@@ -947,7 +970,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: {
@@ -977,7 +1000,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_CLOSE_SESSION: {
@@ -1002,7 +1025,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_REQUEST_CANCELLATION: {
@@ -1028,7 +1051,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_CONTINUE_BLOCKED_REQ_COMMAND: {
@@ -1043,7 +1066,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.arginfo =
TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID;
desc.args[0] = req->app_or_session_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
default: {
@@ -6413,7 +6436,7 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
if (ret)
break;
- ret = scm_call2(TZ_MDTP_CIPHER_DIP_ID, &desc);
+ ret = __qseecom_scm_call2_locked(TZ_MDTP_CIPHER_DIP_ID, &desc);
__qseecom_disable_clk(CLK_QSEE);
@@ -8676,8 +8699,10 @@ static int qseecom_probe(struct platform_device *pdev)
qseecom.send_resp_flag = 0;
qseecom.qsee_version = QSEEE_VERSION_00;
+ mutex_lock(&app_access_lock);
rc = qseecom_scm_call(6, 3, &feature, sizeof(feature),
&resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
pr_info("qseecom.qsee_version = 0x%x\n", resp.result);
if (rc) {
pr_err("Failed to get QSEE version info %d\n", rc);
@@ -8824,9 +8849,11 @@ static int qseecom_probe(struct platform_device *pdev)
rc = -EIO;
goto exit_deinit_clock;
}
+ mutex_lock(&app_access_lock);
rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
cmd_buf, cmd_len,
&resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
__qseecom_disable_clk(CLK_QSEE);
if (rc || (resp.result != QSEOS_RESULT_SUCCESS)) {
pr_err("send secapp reg fail %d resp.res %d\n",