summaryrefslogtreecommitdiff
path: root/drivers/char/adsprpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/adsprpc.c')
-rw-r--r--drivers/char/adsprpc.c180
1 files changed, 131 insertions, 49 deletions
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 95dca75efde9..3c8c1f9acbfa 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -53,8 +53,10 @@
#define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
#define TZ_PIL_AUTH_QDSP6_PROC 1
#define ADSP_MMAP_HEAP_ADDR 4
+#define ADSP_MMAP_REMOTE_HEAP_ADDR 8
#define FASTRPC_ENOSUCH 39
#define VMID_SSC_Q6 5
+#define VMID_ADSP_Q6 6
#define DEBUGFS_SIZE 1024
#define RPC_TIMEOUT (5 * HZ)
@@ -179,6 +181,7 @@ struct fastrpc_ctx_lst {
};
struct fastrpc_smmu {
+ struct device *dev;
struct dma_iommu_mapping *mapping;
int cb;
int enabled;
@@ -354,7 +357,7 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
hyp_assign_phys(buf->phys, buf_page_size(buf->size),
srcVM, 2, destVM, destVMperm, 1);
}
- dma_free_coherent(fl->sctx->dev, buf->size, buf->virt,
+ dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt,
buf->phys);
}
kfree(buf);
@@ -380,7 +383,8 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl)
static void fastrpc_mmap_add(struct fastrpc_mmap *map)
{
- if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ if (map->flags == ADSP_MMAP_HEAP_ADDR ||
+ map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
struct fastrpc_apps *me = &gfa;
spin_lock(&me->hlock);
@@ -401,7 +405,8 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va,
struct fastrpc_apps *me = &gfa;
struct fastrpc_mmap *match = 0, *map;
struct hlist_node *n;
- if (mflags == ADSP_MMAP_HEAP_ADDR) {
+ if (mflags == ADSP_MMAP_HEAP_ADDR ||
+ mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
spin_lock(&me->hlock);
hlist_for_each_entry_safe(map, n, &me->maps, hn) {
if (va >= map->va &&
@@ -505,7 +510,8 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
if (!map)
return;
fl = map->fl;
- if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ if (map->flags == ADSP_MMAP_HEAP_ADDR ||
+ map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
spin_lock(&me->hlock);
map->refs--;
if (!map->refs)
@@ -520,11 +526,8 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
}
if (map->refs > 0)
return;
- if (map->secure)
- sess = fl->secsctx;
- else
- sess = fl->sctx;
- if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ if (map->flags == ADSP_MMAP_HEAP_ADDR ||
+ map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
DEFINE_DMA_ATTRS(attrs);
if (me->dev == NULL) {
@@ -541,11 +544,16 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
int destVM[1] = {VMID_HLOS};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+ if (map->secure)
+ sess = fl->secsctx;
+ else
+ sess = fl->sctx;
+
if (!IS_ERR_OR_NULL(map->handle))
ion_free(fl->apps->client, map->handle);
if (sess->smmu.enabled) {
if (map->size || map->phys)
- msm_dma_unmap_sg(sess->dev,
+ msm_dma_unmap_sg(sess->smmu.dev,
map->table->sgl,
map->table->nents, DMA_BIDIRECTIONAL,
map->buf);
@@ -598,7 +606,8 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
map->fl = fl;
map->fd = fd;
map->attr = attr;
- if (mflags == ADSP_MMAP_HEAP_ADDR) {
+ if (mflags == ADSP_MMAP_HEAP_ADDR ||
+ mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
map->apps = me;
map->fl = 0;
VERIFY(err, !dma_alloc_memory(&region_start, len));
@@ -606,6 +615,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
goto bail;
map->phys = (uintptr_t)region_start;
map->size = len;
+ map->va = map->phys;
} else {
VERIFY(err, !IS_ERR_OR_NULL(map->handle =
ion_import_dma_buf(fl->apps->client, fd)));
@@ -637,7 +647,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
if (err)
goto bail;
VERIFY(err, !IS_ERR_OR_NULL(map->attach =
- dma_buf_attach(map->buf, sess->dev)));
+ dma_buf_attach(map->buf, sess->smmu.dev)));
if (err)
goto bail;
VERIFY(err, !IS_ERR_OR_NULL(map->table =
@@ -656,7 +666,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
dma_set_attr(DMA_ATTR_FORCE_COHERENT, &attrs);
VERIFY(err, map->table->nents ==
- msm_dma_map_sg_attrs(sess->dev,
+ msm_dma_map_sg_attrs(sess->smmu.dev,
map->table->sgl, map->table->nents,
DMA_BIDIRECTIONAL, map->buf, &attrs));
if (err)
@@ -686,8 +696,8 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
if (err)
goto bail;
}
+ map->va = va;
}
- map->va = va;
map->len = len;
fastrpc_mmap_add(map);
@@ -732,12 +742,12 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size,
buf->virt = 0;
buf->phys = 0;
buf->size = size;
- buf->virt = dma_alloc_coherent(fl->sctx->dev, buf->size,
+ buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size,
(void *)&buf->phys, GFP_KERNEL);
if (IS_ERR_OR_NULL(buf->virt)) {
/* free cache and retry */
fastrpc_buf_list_free(fl);
- buf->virt = dma_alloc_coherent(fl->sctx->dev, buf->size,
+ buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size,
(void *)&buf->phys, GFP_KERNEL);
VERIFY(err, !IS_ERR_OR_NULL(buf->virt));
}
@@ -1573,6 +1583,56 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
if (err)
goto bail;
+ } else if (init->flags == FASTRPC_INIT_CREATE_STATIC) {
+ int srcVM[1] = {VMID_HLOS};
+ int destVM[1] = {VMID_ADSP_Q6};
+ int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+ remote_arg_t ra[3];
+ uint64_t phys = 0;
+ ssize_t size;
+ int fds[3];
+ char *proc_name = (unsigned char *)init->file;
+ struct {
+ int pgid;
+ int namelen;
+ int pageslen;
+ } inbuf;
+ inbuf.pgid = current->tgid;
+ inbuf.namelen = strlen(proc_name)+1;
+ inbuf.pageslen = 1;
+ VERIFY(err, !fastrpc_mmap_create(fl, -1, 0, init->mem,
+ init->memlen, ADSP_MMAP_HEAP_ADDR, &mem));
+ phys = mem->phys;
+ size = mem->size;
+ VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size,
+ srcVM, 1, destVM, destVMperm, 1));
+ if (err)
+ goto bail;
+
+ ra[0].buf.pv = (void *)&inbuf;
+ ra[0].buf.len = sizeof(inbuf);
+ fds[0] = 0;
+
+ ra[1].buf.pv = (void *)proc_name;
+ ra[1].buf.len = inbuf.namelen;
+ fds[1] = 0;
+
+ pages[0].addr = phys;
+ pages[0].size = size;
+
+ ra[2].buf.pv = (void *)pages;
+ ra[2].buf.len = sizeof(*pages);
+ fds[2] = 0;
+ ioctl.inv.handle = 1;
+
+ ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 3, 0);
+ ioctl.inv.pra = ra;
+ ioctl.fds = 0;
+ ioctl.attrs = 0;
+ VERIFY(err, !(err = fastrpc_internal_invoke(fl,
+ FASTRPC_MODE_PARALLEL, 1, &ioctl)));
+ if (err)
+ goto bail;
} else {
err = -ENOTTY;
}
@@ -1662,8 +1722,17 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
desc.arginfo = SCM_ARGS(3);
err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc);
- }
+ } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+
+ int srcVM[1] = {VMID_HLOS};
+ int destVM[1] = {VMID_ADSP_Q6};
+ int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+ VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size,
+ srcVM, 1, destVM, destVMperm, 1));
+ if (err)
+ goto bail;
+ }
bail:
return err;
}
@@ -1671,34 +1740,46 @@ bail:
static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
struct fastrpc_mmap *map)
{
- struct fastrpc_ioctl_invoke_attrs ioctl;
- struct scm_desc desc = {0};
- remote_arg_t ra[1];
int err = 0;
- struct {
- uint8_t skey;
- } routargs;
+ int srcVM[1] = {VMID_ADSP_Q6};
+ int destVM[1] = {VMID_HLOS};
+ int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
- ra[0].buf.pv = (void *)&routargs;
- ra[0].buf.len = sizeof(routargs);
+ if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ struct fastrpc_ioctl_invoke_attrs ioctl;
+ struct scm_desc desc = {0};
+ remote_arg_t ra[1];
+ int err = 0;
+ struct {
+ uint8_t skey;
+ } routargs;
- ioctl.inv.handle = 1;
- ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1);
- ioctl.inv.pra = ra;
- ioctl.fds = 0;
- ioctl.attrs = 0;
+ ra[0].buf.pv = (void *)&routargs;
+ ra[0].buf.len = sizeof(routargs);
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
- FASTRPC_MODE_PARALLEL, 1, &ioctl)));
- if (err)
- goto bail;
- desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC;
- desc.args[1] = map->phys;
- desc.args[2] = map->size;
- desc.args[3] = routargs.skey;
- desc.arginfo = SCM_ARGS(4);
- err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
- TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc);
+ ioctl.inv.handle = 1;
+ ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1);
+ ioctl.inv.pra = ra;
+ ioctl.fds = 0;
+ ioctl.attrs = 0;
+
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
+ FASTRPC_MODE_PARALLEL, 1, &ioctl)));
+ if (err)
+ goto bail;
+ desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC;
+ desc.args[1] = map->phys;
+ desc.args[2] = map->size;
+ desc.args[3] = routargs.skey;
+ desc.arginfo = SCM_ARGS(4);
+ err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
+ TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc);
+ } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size,
+ srcVM, 1, destVM, destVMperm, 1));
+ if (err)
+ goto bail;
+ }
bail:
return err;
@@ -1715,7 +1796,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
uintptr_t vaddrout;
ssize_t size;
} inargs;
- if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ if (map->flags == ADSP_MMAP_HEAP_ADDR ||
+ map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map));
if (err)
goto bail;
@@ -2554,7 +2636,7 @@ static int fastrpc_cb_probe(struct device *dev)
VERIFY(err, !arm_iommu_attach_device(dev, sess->smmu.mapping));
if (err)
goto bail;
- sess->dev = dev;
+ sess->smmu.dev = dev;
sess->smmu.enabled = 1;
chan->sesscount++;
debugfs_global_file = debugfs_create_file("global", 0644, debugfs_root,
@@ -2619,10 +2701,10 @@ static int fastrpc_cb_legacy_probe(struct device *dev)
if (err)
goto bail;
first_sess = &chan->session[chan->sesscount];
- first_sess->dev = msm_iommu_get_ctx(name);
+ first_sess->smmu.dev = msm_iommu_get_ctx(name);
VERIFY(err, !IS_ERR_OR_NULL(first_sess->smmu.mapping =
arm_iommu_create_mapping(
- msm_iommu_get_bus(first_sess->dev),
+ msm_iommu_get_bus(first_sess->smmu.dev),
range[0], range[1])));
if (err)
goto bail;
@@ -2636,7 +2718,7 @@ static int fastrpc_cb_legacy_probe(struct device *dev)
goto bail;
sess = &chan->session[chan->sesscount];
sess->smmu.cb = sids[i];
- sess->dev = first_sess->dev;
+ sess->smmu.dev = first_sess->smmu.dev;
sess->smmu.enabled = 1;
sess->smmu.mapping = first_sess->smmu.mapping;
chan->sesscount++;
@@ -2696,9 +2778,9 @@ static void fastrpc_deinit(void)
}
for (j = 0; j < NUM_SESSIONS; j++) {
struct fastrpc_session_ctx *sess = &chan->session[j];
- if (sess->smmu.enabled) {
- arm_iommu_detach_device(sess->dev);
- sess->dev = 0;
+ if (sess->smmu.dev) {
+ arm_iommu_detach_device(sess->smmu.dev);
+ sess->smmu.dev = 0;
}
if (sess->smmu.mapping) {
arm_iommu_release_mapping(sess->smmu.mapping);