mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
Merge "qtee_shmbridge: register bridges for CMA heaps"
This commit is contained in:
commit
2ac873fba2
2 changed files with 134 additions and 5 deletions
|
|
@ -11,8 +11,11 @@
|
|||
#include <linux/genalloc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/msm_ion.h>
|
||||
#include <soc/qcom/qseecomi.h>
|
||||
#include <linux/qtee_shmbridge.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
|
@ -78,6 +81,18 @@ struct bridge_list_entry {
|
|||
uint64_t handle;
|
||||
};
|
||||
|
||||
struct cma_heap_bridge_info {
|
||||
uint32_t heapid;
|
||||
uint64_t handle;
|
||||
};
|
||||
|
||||
enum CMA_HEAP_TYPE {
|
||||
QSEECOM_HEAP = 0,
|
||||
QSEECOM_TA_HEAP,
|
||||
USER_CONTI_HEAP,
|
||||
HEAP_TYPE_MAX
|
||||
};
|
||||
|
||||
static struct bridge_info default_bridge;
|
||||
static struct bridge_list bridge_list_head;
|
||||
static bool qtee_shmbridge_enabled;
|
||||
|
|
@ -390,11 +405,12 @@ static int qtee_shmbridge_init(struct platform_device *pdev)
|
|||
mutex_init(&bridge_list_head.lock);
|
||||
INIT_LIST_HEAD(&bridge_list_head.head);
|
||||
|
||||
/* temporarily disable shm bridge mechanism */
|
||||
ret = qtee_shmbridge_enable(true);
|
||||
if (ret) {
|
||||
/* keep the mem pool and return if failed to enable bridge */
|
||||
ret = 0;
|
||||
goto exit;
|
||||
goto exit_shmbridge_enable;
|
||||
}
|
||||
|
||||
/*register default bridge*/
|
||||
|
|
@ -412,7 +428,7 @@ static int qtee_shmbridge_init(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
pr_err("Failed to register default bridge, size %zu\n",
|
||||
default_bridge.size);
|
||||
goto exit;
|
||||
goto exit_deregister_default_bridge;
|
||||
}
|
||||
|
||||
pr_debug("qtee shmbridge registered default bridge with size %d bytes\n",
|
||||
|
|
@ -420,6 +436,10 @@ static int qtee_shmbridge_init(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
exit_deregister_default_bridge:
|
||||
qtee_shmbridge_deregister(default_bridge.handle);
|
||||
exit_shmbridge_enable:
|
||||
qtee_shmbridge_enable(false);
|
||||
exit_destroy_pool:
|
||||
gen_pool_destroy(default_bridge.genpool);
|
||||
exit_unmap:
|
||||
|
|
@ -427,7 +447,8 @@ exit_unmap:
|
|||
DMA_TO_DEVICE);
|
||||
exit_freebuf:
|
||||
free_pages((long)default_bridge.vaddr, get_order(default_bridge.size));
|
||||
exit:
|
||||
default_bridge.vaddr = NULL;
|
||||
//exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -439,6 +460,16 @@ static int qtee_shmbridge_probe(struct platform_device *pdev)
|
|||
return qtee_shmbridge_init(pdev);
|
||||
}
|
||||
|
||||
static int qtee_shmbridge_remove(struct platform_device *pdev)
|
||||
{
|
||||
qtee_shmbridge_deregister(default_bridge.handle);
|
||||
gen_pool_destroy(default_bridge.genpool);
|
||||
dma_unmap_single(&pdev->dev, default_bridge.paddr, default_bridge.size,
|
||||
DMA_TO_DEVICE);
|
||||
free_pages((long)default_bridge.vaddr, get_order(default_bridge.size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qtee_shmbridge_of_match[] = {
|
||||
{ .compatible = "qcom,tee-shared-memory-bridge"},
|
||||
{}
|
||||
|
|
@ -447,6 +478,7 @@ MODULE_DEVICE_TABLE(of, qtee_shmbridge_of_match);
|
|||
|
||||
static struct platform_driver qtee_shmbridge_driver = {
|
||||
.probe = qtee_shmbridge_probe,
|
||||
.remove = qtee_shmbridge_remove,
|
||||
.driver = {
|
||||
.name = "shared_memory_bridge",
|
||||
.of_match_table = qtee_shmbridge_of_match,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/dma-buf.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/msm_ion.h>
|
||||
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
|
@ -249,6 +250,8 @@ struct smcinvoke_mem_obj {
|
|||
uint64_t p_addr;
|
||||
size_t p_addr_len;
|
||||
struct list_head list;
|
||||
bool bridge_created_by_others;
|
||||
uint64_t shmbridge_handle;
|
||||
};
|
||||
|
||||
static void destroy_cb_server(struct kref *kref)
|
||||
|
|
@ -357,6 +360,8 @@ static inline void free_mem_obj_locked(struct smcinvoke_mem_obj *mem_obj)
|
|||
{
|
||||
list_del(&mem_obj->list);
|
||||
dma_buf_put(mem_obj->dma_buf);
|
||||
if (!mem_obj->bridge_created_by_others)
|
||||
qtee_shmbridge_deregister(mem_obj->shmbridge_handle);
|
||||
kfree(mem_obj);
|
||||
}
|
||||
|
||||
|
|
@ -788,6 +793,82 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int smcinvoke_create_bridge(struct smcinvoke_mem_obj *mem_obj)
|
||||
{
|
||||
int ret = 0, i;
|
||||
int tz_perm = PERM_READ|PERM_WRITE;
|
||||
uint32_t *vmid_list;
|
||||
uint32_t *perms_list;
|
||||
uint32_t nelems = 0;
|
||||
unsigned long dma_buf_flags = 0;
|
||||
struct dma_buf *dmabuf = mem_obj->dma_buf;
|
||||
phys_addr_t phys = mem_obj->p_addr;
|
||||
size_t size = mem_obj->p_addr_len;
|
||||
|
||||
if (!qtee_shmbridge_is_enabled())
|
||||
return 0;
|
||||
|
||||
ret = dma_buf_get_flags(dmabuf, &dma_buf_flags);
|
||||
if (ret) {
|
||||
pr_err("failed to get dmabuf flag for mem_region_id %d\n",
|
||||
mem_obj->mem_region_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dma_buf_flags & ION_FLAG_SECURE)
|
||||
nelems = ion_get_flags_num_vm_elems(dma_buf_flags);
|
||||
else
|
||||
nelems = 1;
|
||||
|
||||
vmid_list = kcalloc(nelems, sizeof(*vmid_list), GFP_KERNEL);
|
||||
if (!vmid_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
perms_list = kcalloc(nelems, sizeof(*perms_list), GFP_KERNEL);
|
||||
if (!perms_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_free_vmid_list;
|
||||
}
|
||||
|
||||
if (dma_buf_flags & ION_FLAG_SECURE) {
|
||||
ret = ion_populate_vm_list(dma_buf_flags, vmid_list, nelems);
|
||||
if (ret)
|
||||
goto exit_free_vmid_list;
|
||||
|
||||
for (i = 0; i < nelems; i++)
|
||||
perms_list[i] = msm_secure_get_vmid_perms(vmid_list[i]);
|
||||
} else {
|
||||
vmid_list[0] = VMID_HLOS;
|
||||
perms_list[0] = PERM_READ | PERM_WRITE;
|
||||
}
|
||||
|
||||
ret = qtee_shmbridge_register(phys, size, vmid_list, perms_list, nelems,
|
||||
tz_perm, &mem_obj->shmbridge_handle);
|
||||
|
||||
if (ret && ret != -EEXIST) {
|
||||
pr_err("creation of shm bridge for mem_region_id %d failed ret %d\n",
|
||||
mem_obj->mem_region_id, ret);
|
||||
goto exit_free_perms_list;
|
||||
}
|
||||
|
||||
if (ret == -EEXIST) {
|
||||
mem_obj->bridge_created_by_others = true;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
pr_debug("created shm bridge handle %lld for mem_region_id %d\n",
|
||||
mem_obj->shmbridge_handle, mem_obj->mem_region_id);
|
||||
|
||||
exit_free_perms_list:
|
||||
kfree(perms_list);
|
||||
exit_free_vmid_list:
|
||||
kfree(vmid_list);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t smcinvoke_release_mem_obj_locked(void *buf, size_t buf_len)
|
||||
{
|
||||
struct smcinvoke_tzcb_req *msg = buf;
|
||||
|
|
@ -845,8 +926,9 @@ static int32_t smcinvoke_map_mem_region(void *buf, size_t buf_len)
|
|||
|
||||
sgt = dma_buf_map_attachment(buf_attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR(sgt)) {
|
||||
pr_err("mapping dma buffers failed, ret: %d\n",
|
||||
PTR_ERR(sgt));
|
||||
ret = OBJECT_ERROR_KMEM;
|
||||
pr_err("mapping dma buffers failed, ret: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
mem_obj->sgt = sgt;
|
||||
|
|
@ -864,6 +946,11 @@ static int32_t smcinvoke_map_mem_region(void *buf, size_t buf_len)
|
|||
pr_err("invalid physical address, ret: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = smcinvoke_create_bridge(mem_obj);
|
||||
if (ret) {
|
||||
ret = OBJECT_ERROR_INVALID;
|
||||
goto out;
|
||||
}
|
||||
mem_obj->mem_map_obj_id = next_mem_map_obj_id_locked();
|
||||
} else {
|
||||
kref_get(&mem_obj->mem_map_obj_ref_cnt);
|
||||
|
|
@ -974,7 +1061,12 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
|
|||
TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle));
|
||||
if (!srvr_info || srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT) {
|
||||
/* ret equals Object_ERROR_DEFUNCT, at this point go to out */
|
||||
pr_err("sever is either invalid or defunct\n");
|
||||
if (!srvr_info)
|
||||
pr_err("server is invalid\n");
|
||||
else {
|
||||
pr_err("server is defunct, state= %d tzhandle = %d\n",
|
||||
srvr_info->state, cb_req->hdr.tzhandle);
|
||||
}
|
||||
mutex_unlock(&g_smcinvoke_lock);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1928,6 +2020,11 @@ static int smcinvoke_probe(struct platform_device *pdev)
|
|||
goto exit_destroy_device;
|
||||
}
|
||||
smcinvoke_pdev = pdev;
|
||||
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (rc) {
|
||||
pr_err("dma_set_mask_and_coherent failed %d\n", rc);
|
||||
goto exit_destroy_device;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue