Loading drivers/soc/qcom/scm.c +39 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/cacheflush.h> #include <asm/compiler.h> Loading @@ -29,9 +30,13 @@ #define SCM_EINVAL_ARG -2 #define SCM_ERROR -1 #define SCM_INTERRUPTED 1 #define SCM_EBUSY -55 static DEFINE_MUTEX(scm_lock); #define SCM_EBUSY_WAIT_MS 30 #define SCM_EBUSY_MAX_RETRY 20 #define SCM_BUF_LEN(__cmd_size, __resp_size) \ (sizeof(struct scm_command) + sizeof(struct scm_response) + \ __cmd_size + __resp_size) Loading Loading @@ -139,6 +144,7 @@ static inline void *scm_get_response_buffer(const struct scm_response *rsp) static int scm_remap_error(int err) { if (err != SCM_EBUSY) pr_err("scm_call failed with error code %d\n", err); switch (err) { case SCM_ERROR: Loading @@ -150,6 +156,8 @@ static int scm_remap_error(int err) return -EOPNOTSUPP; case SCM_ENOMEM: return -ENOMEM; case SCM_EBUSY: return SCM_EBUSY; } return -EINVAL; } Loading Loading @@ -281,6 +289,33 @@ static int scm_call_common(u32 svc_id, u32 cmd_id, const void *cmd_buf, return ret; } /* * Sometimes the secure world may be busy waiting for a particular resource. * In those situations, it is expected that the secure world returns a special * error code (SCM_EBUSY). Retry any scm_call that fails with this error code, * but with a timeout in place. Also, don't move this into scm_call_common, * since we want the first attempt to be the "fastpath". */ static int _scm_call_retry(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len, struct scm_command *cmd, size_t len) { int ret, retry_count = 0; do { ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, len); if (ret == SCM_EBUSY) msleep(SCM_EBUSY_WAIT_MS); } while (ret == SCM_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); if (ret == SCM_EBUSY) pr_err("scm: secure world busy (rc = SCM_EBUSY)\n"); return ret; } /** * scm_call_noalloc - Send an SCM command * Loading Loading @@ -344,6 +379,9 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, len); if (unlikely(ret == SCM_EBUSY)) ret = _scm_call_retry(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, PAGE_ALIGN(len)); kfree(cmd); return ret; } Loading Loading
drivers/soc/qcom/scm.c +39 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/cacheflush.h> #include <asm/compiler.h> Loading @@ -29,9 +30,13 @@ #define SCM_EINVAL_ARG -2 #define SCM_ERROR -1 #define SCM_INTERRUPTED 1 #define SCM_EBUSY -55 static DEFINE_MUTEX(scm_lock); #define SCM_EBUSY_WAIT_MS 30 #define SCM_EBUSY_MAX_RETRY 20 #define SCM_BUF_LEN(__cmd_size, __resp_size) \ (sizeof(struct scm_command) + sizeof(struct scm_response) + \ __cmd_size + __resp_size) Loading Loading @@ -139,6 +144,7 @@ static inline void *scm_get_response_buffer(const struct scm_response *rsp) static int scm_remap_error(int err) { if (err != SCM_EBUSY) pr_err("scm_call failed with error code %d\n", err); switch (err) { case SCM_ERROR: Loading @@ -150,6 +156,8 @@ static int scm_remap_error(int err) return -EOPNOTSUPP; case SCM_ENOMEM: return -ENOMEM; case SCM_EBUSY: return SCM_EBUSY; } return -EINVAL; } Loading Loading @@ -281,6 +289,33 @@ static int scm_call_common(u32 svc_id, u32 cmd_id, const void *cmd_buf, return ret; } /* * Sometimes the secure world may be busy waiting for a particular resource. * In those situations, it is expected that the secure world returns a special * error code (SCM_EBUSY). Retry any scm_call that fails with this error code, * but with a timeout in place. Also, don't move this into scm_call_common, * since we want the first attempt to be the "fastpath". */ static int _scm_call_retry(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len, struct scm_command *cmd, size_t len) { int ret, retry_count = 0; do { ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, len); if (ret == SCM_EBUSY) msleep(SCM_EBUSY_WAIT_MS); } while (ret == SCM_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); if (ret == SCM_EBUSY) pr_err("scm: secure world busy (rc = SCM_EBUSY)\n"); return ret; } /** * scm_call_noalloc - Send an SCM command * Loading Loading @@ -344,6 +379,9 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, len); if (unlikely(ret == SCM_EBUSY)) ret = _scm_call_retry(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len, cmd, PAGE_ALIGN(len)); kfree(cmd); return ret; } Loading