mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
firmware: qcom_scm: Use qtee_shmbridge if available
Secure world imposed that buffer exchanges between secure and non-secure worlds be allocated from qtee_shmbridge, so add a function to allocate buffer space using shmbridge for extra arguments. Change helps in dealing with early scm calls when the driver is not initialized. Change-Id: I270b4aef9d33ec6d7ea0897ddcc0944ac9e1833f Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
parent
4d0fbd6baf
commit
bbf72fdcb6
2 changed files with 41 additions and 18 deletions
|
|
@ -12,6 +12,10 @@
|
|||
#include <linux/arm-smccc.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <linux/qtee_shmbridge.h>
|
||||
|
||||
#include "qcom_scm.h"
|
||||
|
||||
#define MAX_QCOM_SCM_ARGS 10
|
||||
|
|
@ -180,17 +184,17 @@ static int qcom_scm_call_smccc(struct device *dev,
|
|||
struct qcom_scm_desc *desc, bool atomic)
|
||||
{
|
||||
int arglen = desc->arginfo & 0xf;
|
||||
int i;
|
||||
dma_addr_t args_phys = 0;
|
||||
void *args_virt = NULL;
|
||||
int i, ret;
|
||||
size_t alloc_len;
|
||||
gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
gfp_t flag = atomic ? GFP_ATOMIC : GFP_NOIO;
|
||||
u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
|
||||
u32 qcom_smccc_convention =
|
||||
(qcom_smc_convention == SMC_CONVENTION_ARM_32) ?
|
||||
ARM_SMCCC_SMC_32 : ARM_SMCCC_SMC_64;
|
||||
struct arm_smccc_res res;
|
||||
struct arm_smccc_args smc = {{0}};
|
||||
struct qtee_shm shm = {0};
|
||||
bool use_qtee_shmbridge;
|
||||
|
||||
smc.a[0] = ARM_SMCCC_CALL_VAL(
|
||||
smccc_call_type,
|
||||
|
|
@ -206,34 +210,43 @@ static int qcom_scm_call_smccc(struct device *dev,
|
|||
return -EPROBE_DEFER;
|
||||
|
||||
alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64);
|
||||
args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag);
|
||||
|
||||
if (!args_virt)
|
||||
return -ENOMEM;
|
||||
use_qtee_shmbridge = qtee_shmbridge_is_enabled();
|
||||
if (use_qtee_shmbridge) {
|
||||
ret = qtee_shmbridge_allocate_shm(alloc_len, &shm);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
shm.vaddr = kzalloc(alloc_len, flag);
|
||||
if (!shm.vaddr)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (qcom_smc_convention == SMC_CONVENTION_ARM_32) {
|
||||
__le32 *args = args_virt;
|
||||
__le32 *args = shm.vaddr;
|
||||
|
||||
for (i = 0; i < SMCCC_N_EXT_ARGS; i++)
|
||||
args[i] = cpu_to_le32(desc->args[i +
|
||||
SMCCC_FIRST_EXT_IDX]);
|
||||
} else {
|
||||
__le64 *args = args_virt;
|
||||
__le64 *args = shm.vaddr;
|
||||
|
||||
for (i = 0; i < SMCCC_N_EXT_ARGS; i++)
|
||||
args[i] = cpu_to_le64(desc->args[i +
|
||||
SMCCC_FIRST_EXT_IDX]);
|
||||
}
|
||||
|
||||
args_phys = dma_map_single(dev, args_virt, alloc_len,
|
||||
DMA_TO_DEVICE);
|
||||
shm.paddr = dma_map_single(dev, shm.vaddr, alloc_len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (dma_mapping_error(dev, args_phys)) {
|
||||
kfree(args_virt);
|
||||
if (dma_mapping_error(dev, shm.paddr)) {
|
||||
if (use_qtee_shmbridge)
|
||||
qtee_shmbridge_free_shm(&shm);
|
||||
else
|
||||
kfree(shm.vaddr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
smc.a[SMCCC_LAST_REG_IDX] = args_phys;
|
||||
smc.a[SMCCC_LAST_REG_IDX] = shm.paddr;
|
||||
}
|
||||
|
||||
if (atomic) {
|
||||
|
|
@ -256,9 +269,13 @@ static int qcom_scm_call_smccc(struct device *dev,
|
|||
} while (res.a0 == QCOM_SCM_V2_EBUSY);
|
||||
}
|
||||
|
||||
if (args_virt) {
|
||||
dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
|
||||
kfree(args_virt);
|
||||
if (unlikely(arglen > SMCCC_N_REG_ARGS)) {
|
||||
dma_unmap_single(dev, shm.paddr, alloc_len,
|
||||
DMA_TO_DEVICE);
|
||||
if (use_qtee_shmbridge)
|
||||
qtee_shmbridge_free_shm(&shm);
|
||||
else
|
||||
kfree(shm.vaddr);
|
||||
}
|
||||
|
||||
desc->res[0] = res.a1;
|
||||
|
|
|
|||
|
|
@ -580,6 +580,12 @@ static int qcom_scm_probe(struct platform_device *pdev)
|
|||
|
||||
__qcom_scm_init();
|
||||
|
||||
#if CONFIG_ARM64
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If requested enable "download mode", from this point on warmboot
|
||||
* will cause the the boot stages to enter download mode, unless
|
||||
|
|
|
|||
Loading…
Reference in a new issue