diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 84b39414a315..1b6f180bf011 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -863,16 +863,22 @@ static int fastrpc_alloc_cma_memory(dma_addr_t *region_phys, void **vaddr, return 0; } -static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, +static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, size_t len, struct fastrpc_mmap **ppmap) { struct fastrpc_mmap *match = NULL, *map; struct hlist_node *n; struct fastrpc_apps *me = &gfa; + /* + * Search for a mapping by matching fd, remote address and length. + * For backward compatibility, search for a mapping by matching is + * limited to remote address and length when passed fd < 0. + */ + spin_lock(&me->hlock); hlist_for_each_entry_safe(map, n, &me->maps, hn) { - if (map->raddr == va && + if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; @@ -886,7 +892,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - if (map->raddr == va && + if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; @@ -898,7 +904,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, *ppmap = match; return 0; } - return -ENOTTY; + return -ETOOMANYREFS; } static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) @@ -3353,6 +3359,106 @@ bail: return err; } +static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset, + uint32_t flags, uintptr_t va, uint64_t phys, + size_t size, uintptr_t *raddr) +{ + struct fastrpc_ioctl_invoke_async ioctl; + struct smq_phy_page page; + remote_arg_t ra[4]; + int err = 0; + struct { + int pid; + int fd; + int offset; + uint32_t flags; + uint64_t vaddrin; + int num; + int data_len; + } inargs; + struct { + uint64_t vaddrout; + } routargs; + + inargs.pid = fl->tgid; + inargs.fd = fd; + inargs.offset = offset; + inargs.vaddrin = (uintptr_t)va; + inargs.flags = flags; + inargs.num = sizeof(page); + inargs.data_len = 0; + ra[0].buf.pv = (void *)&inargs; + ra[0].buf.len = sizeof(inargs); + page.addr = phys; + page.size = size; + ra[1].buf.pv = (void *)&page; + ra[1].buf.len = sizeof(page); + ra[2].buf.pv = (void *)&page; + ra[2].buf.len = 0; + ra[3].buf.pv = (void *)&routargs; + ra[3].buf.len = sizeof(routargs); + + ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; + ioctl.inv.sc = REMOTE_SCALARS_MAKE(10, 3, 1); + ioctl.inv.pra = ra; + ioctl.fds = NULL; + ioctl.attrs = NULL; + ioctl.crc = NULL; + ioctl.job = NULL; + VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, + FASTRPC_MODE_PARALLEL, 1, &ioctl))); + if (err) + goto bail; + if (raddr) + *raddr = (uintptr_t)routargs.vaddrout; +bail: + if (err) { + pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", + __func__, err, fd, size); + } + return err; +} + +static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd, + uint32_t flags, uintptr_t va, + uint64_t phys, size_t size) +{ + struct fastrpc_ioctl_invoke_async ioctl; + remote_arg_t ra[1]; + int err = 0; + struct { + int pid; + int fd; + uint64_t vaddrin; + uint64_t len; + } inargs; + + inargs.pid = fl->tgid; + inargs.fd = fd; + inargs.vaddrin = (uint64_t)va; + inargs.len = (uint64_t)size; + ra[0].buf.pv = (void *)&inargs; + ra[0].buf.len = sizeof(inargs); + + ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; + ioctl.inv.sc = REMOTE_SCALARS_MAKE(11, 1, 0); + ioctl.inv.pra = ra; + ioctl.fds = NULL; + ioctl.attrs = NULL; + ioctl.crc = NULL; + ioctl.job = NULL; + VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, + FASTRPC_MODE_PARALLEL, 1, &ioctl))); + if (err) + goto bail; +bail: + if (err) { + pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", + __func__, err, fd, size); + } + return err; +} + static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, uint64_t phys, size_t size, uint32_t flags) { @@ -3686,7 +3792,7 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, } mutex_lock(&fl->map_mutex); - VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); + VERIFY(err, !fastrpc_mmap_remove(fl, -1, ud->vaddrout, ud->size, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; @@ -3739,6 +3845,106 @@ bail: return err; } +static int fastrpc_internal_mem_map(struct fastrpc_file *fl, + struct fastrpc_ioctl_mem_map *ud) +{ + int err = 0; + struct fastrpc_mmap *map = NULL; + + VERIFY(err, fl->dsp_proc_init == 1); + if (err) { + pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", + __func__, current->comm); + err = EBADR; + goto bail; + } + + /* create SMMU mapping */ + mutex_lock(&fl->map_mutex); + VERIFY(err, !fastrpc_mmap_create(fl, ud->m.fd, ud->m.attrs, + ud->m.vaddrin, ud->m.length, + ud->m.flags, &map)); + mutex_unlock(&fl->map_mutex); + if (err) + goto bail; + + if (map->raddr) { + err = -EEXIST; + goto bail; + } + + /* create DSP mapping */ + VERIFY(err, !(err = fastrpc_mem_map_to_dsp(fl, ud->m.fd, ud->m.offset, + ud->m.flags, map->va, map->phys, ud->m.length, &map->raddr))); + if (err) + goto bail; + ud->m.vaddrout = map->raddr; +bail: + if (err) { + pr_err("adsprpc: %s failed to map fd %d flags %d err %d\n", + __func__, ud->m.fd, ud->m.flags, err); + if (map) { + mutex_lock(&fl->map_mutex); + fastrpc_mmap_free(map, 0); + mutex_unlock(&fl->map_mutex); + } + } + return err; +} + +static int fastrpc_internal_mem_unmap(struct fastrpc_file *fl, + struct fastrpc_ioctl_mem_unmap *ud) +{ + int err = 0; + struct fastrpc_mmap *map = NULL; + + VERIFY(err, fl->dsp_proc_init == 1); + if (err) { + pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", + __func__, current->comm); + err = EBADR; + goto bail; + } + + mutex_lock(&fl->map_mutex); + VERIFY(err, !fastrpc_mmap_remove(fl, ud->um.fd, + (uintptr_t)ud->um.vaddr, ud->um.length, &map)); + mutex_unlock(&fl->map_mutex); + if (err) + goto bail; + + VERIFY(err, map->flags == FASTRPC_MAP_FD || + map->flags == FASTRPC_MAP_FD_DELAYED || + map->flags == FASTRPC_MAP_STATIC); + if (err) { + err = -EBADMSG; + goto bail; + } + + /* remove mapping on DSP */ + VERIFY(err, !(err = fastrpc_mem_unmap_to_dsp(fl, map->fd, map->flags, + map->raddr, map->phys, map->size))); + if (err) + goto bail; + + /* remove SMMU mapping */ + mutex_lock(&fl->map_mutex); + fastrpc_mmap_free(map, 0); + mutex_unlock(&fl->map_mutex); + map = NULL; +bail: + if (err) { + pr_err("adsprpc: %s failed to unmap fd %d addr 0x%llx length 0x%x err 0x%x\n", + __func__, ud->um.fd, ud->um.vaddr, ud->um.length, err); + /* Add back to map list in case of error to unmap on DSP */ + if (map) { + mutex_lock(&fl->map_mutex); + fastrpc_mmap_add(map); + mutex_unlock(&fl->map_mutex); + } + } + return err; +} static int fastrpc_internal_mmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mmap *ud) @@ -4735,26 +4941,130 @@ bail: return err; } -static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, - unsigned long ioctl_param) +union fastrpc_ioctl_param { + struct fastrpc_ioctl_invoke_async inv; + struct fastrpc_ioctl_mem_map mem_map; + struct fastrpc_ioctl_mem_unmap mem_unmap; + struct fastrpc_ioctl_mmap mmap; + struct fastrpc_ioctl_mmap_64 mmap64; + struct fastrpc_ioctl_munmap munmap; + struct fastrpc_ioctl_munmap_64 munmap64; + struct fastrpc_ioctl_munmap_fd munmap_fd; + struct fastrpc_ioctl_init_attrs init; + struct fastrpc_ioctl_perf perf; + struct fastrpc_ioctl_control cp; + struct fastrpc_ioctl_capability cap; + struct fastrpc_ioctl_invoke2 inv2; +}; + +static inline int fastrpc_mmap_device_ioctl(struct fastrpc_file *fl, + unsigned int ioctl_num, union fastrpc_ioctl_param *p, + void *param) { - union { - struct fastrpc_ioctl_invoke_async inv; - struct fastrpc_ioctl_mmap mmap; - struct fastrpc_ioctl_mmap_64 mmap64; - struct fastrpc_ioctl_munmap munmap; - struct fastrpc_ioctl_munmap_64 munmap64; - struct fastrpc_ioctl_munmap_fd munmap_fd; - struct fastrpc_ioctl_init_attrs init; - struct fastrpc_ioctl_perf perf; - struct fastrpc_ioctl_control cp; - struct fastrpc_ioctl_capability cap; - struct fastrpc_ioctl_invoke2 inv2; - } p; union { struct fastrpc_ioctl_mmap mmap; struct fastrpc_ioctl_munmap munmap; } i; + int err = 0; + + switch (ioctl_num) { + case FASTRPC_IOCTL_MEM_MAP: + K_COPY_FROM_USER(err, 0, &p->mem_map, param, + sizeof(p->mem_map)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl, + &p->mem_map))); + if (err) + goto bail; + K_COPY_TO_USER(err, 0, param, &p->mem_map, sizeof(p->mem_map)); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MEM_UNMAP: + K_COPY_FROM_USER(err, 0, &p->mem_unmap, param, + sizeof(p->mem_unmap)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl, + &p->mem_unmap))); + if (err) + goto bail; + K_COPY_TO_USER(err, 0, param, &p->mem_unmap, + sizeof(p->mem_unmap)); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MMAP: + K_COPY_FROM_USER(err, 0, &p->mmap, param, + sizeof(p->mmap)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p->mmap))); + if (err) + goto bail; + K_COPY_TO_USER(err, 0, param, &p->mmap, sizeof(p->mmap)); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MUNMAP: + K_COPY_FROM_USER(err, 0, &p->munmap, param, + sizeof(p->munmap)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, + &p->munmap))); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MMAP_64: + K_COPY_FROM_USER(err, 0, &p->mmap64, param, + sizeof(p->mmap64)); + if (err) + goto bail; + get_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); + VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); + if (err) + goto bail; + put_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); + K_COPY_TO_USER(err, 0, param, &p->mmap64, sizeof(p->mmap64)); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MUNMAP_64: + K_COPY_FROM_USER(err, 0, &p->munmap64, param, + sizeof(p->munmap64)); + if (err) + goto bail; + get_fastrpc_ioctl_munmap_64(&p->munmap64, &i.munmap); + VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, + &i.munmap))); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MUNMAP_FD: + K_COPY_FROM_USER(err, 0, &p->munmap_fd, param, + sizeof(p->munmap_fd)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, + &p->munmap_fd))); + if (err) + goto bail; + break; + default: + err = -ENOTTY; + pr_info("bad ioctl: %d\n", ioctl_num); + break; + } +bail: + return err; +} + +static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, + unsigned long ioctl_param) +{ + union fastrpc_ioctl_param p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; int size = 0, err = 0; @@ -4811,63 +5121,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; - case FASTRPC_IOCTL_MMAP: - K_COPY_FROM_USER(err, 0, &p.mmap, param, - sizeof(p.mmap)); - if (err) - goto bail; - VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap))); - if (err) - goto bail; - K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap)); - if (err) - goto bail; - break; - case FASTRPC_IOCTL_MUNMAP: - K_COPY_FROM_USER(err, 0, &p.munmap, param, - sizeof(p.munmap)); - if (err) - goto bail; - VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, - &p.munmap))); - if (err) - goto bail; - break; - case FASTRPC_IOCTL_MMAP_64: - K_COPY_FROM_USER(err, 0, &p.mmap64, param, - sizeof(p.mmap64)); - if (err) - goto bail; - get_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); - VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); - if (err) - goto bail; - put_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); - K_COPY_TO_USER(err, 0, param, &p.mmap64, sizeof(p.mmap64)); - if (err) - goto bail; - break; - case FASTRPC_IOCTL_MUNMAP_64: - K_COPY_FROM_USER(err, 0, &p.munmap64, param, - sizeof(p.munmap64)); - if (err) - goto bail; - get_fastrpc_ioctl_munmap_64(&p.munmap64, &i.munmap); - VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, - &i.munmap))); - if (err) - goto bail; - break; - case FASTRPC_IOCTL_MUNMAP_FD: - K_COPY_FROM_USER(err, 0, &p.munmap_fd, param, - sizeof(p.munmap_fd)); - if (err) - goto bail; - VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, - &p.munmap_fd))); - if (err) - goto bail; - break; case FASTRPC_IOCTL_SETMODE: err = fastrpc_setmode(ioctl_param, fl); break; @@ -4906,6 +5159,21 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, case FASTRPC_IOCTL_GET_DSP_INFO: err = fastrpc_get_dsp_info(&p.cap, param, fl); break; + case FASTRPC_IOCTL_MEM_MAP: + /* fall through */ + case FASTRPC_IOCTL_MEM_UNMAP: + /* fall through */ + case FASTRPC_IOCTL_MMAP: + /* fall through */ + case FASTRPC_IOCTL_MUNMAP: + /* fall through */ + case FASTRPC_IOCTL_MMAP_64: + /* fall through */ + case FASTRPC_IOCTL_MUNMAP_64: + /* fall through */ + case FASTRPC_IOCTL_MUNMAP_FD: + err = fastrpc_mmap_device_ioctl(fl, ioctl_num, &p, param); + break; default: err = -ENOTTY; pr_info("bad ioctl: %d\n", ioctl_num); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index 0b6e3c791a9a..88b662ad6c8b 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -39,6 +39,10 @@ struct compat_fastrpc_ioctl_capability) #define COMPAT_FASTRPC_IOCTL_INVOKE2 \ _IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2) +#define COMPAT_FASTRPC_IOCTL_MEM_MAP \ + _IOWR('R', 19, struct compat_fastrpc_ioctl_mem_map) +#define COMPAT_FASTRPC_IOCTL_MEM_UNMAP \ + _IOWR('R', 20, struct compat_fastrpc_ioctl_mem_unmap) struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ @@ -89,6 +93,38 @@ struct compat_fastrpc_ioctl_invoke2 { compat_int_t err; /* reserved */ }; +struct compat_fastrpc_mem_map { + compat_int_t fd; /* ion fd */ + compat_int_t offset; /* buffer offset */ + compat_uint_t flags; /* flags to control memory map */ + compat_uint_t attrs; /* buffer attributes used for SMMU mapping */ + compat_uptr_t vaddrin; /* virtual address */ + compat_size_t length; /* buffer length */ + compat_u64 vaddrout; /* dsp virtual address */ +}; + +struct compat_fastrpc_ioctl_mem_map { + compat_int_t version; + union { + struct compat_fastrpc_mem_map m; + compat_int_t reserved[MAP_RESERVED_NUM]; + }; +}; + +struct compat_fastrpc_mem_unmap { + compat_int_t fd; /* ion fd */ + compat_u64 vaddr; /* dsp virtual address */ + compat_size_t length; /* buffer length */ +}; + +struct compat_fastrpc_ioctl_mem_unmap { + compat_int_t version; + union { + struct compat_fastrpc_mem_unmap um; + compat_int_t reserved[UNMAP_RESERVED_NUM]; + }; +}; + struct compat_fastrpc_ioctl_mmap { compat_int_t fd; /* ion fd */ compat_uint_t flags; /* flags for dsp to map with */ @@ -372,6 +408,74 @@ static int compat_fastrpc_ioctl_invoke2(struct file *filp, FASTRPC_IOCTL_INVOKE2, (unsigned long)inv); } +static int compat_get_fastrpc_ioctl_mem_map( + struct compat_fastrpc_ioctl_mem_map __user *map32, + struct fastrpc_ioctl_mem_map __user *map) +{ + compat_uint_t u; + compat_int_t i; + compat_size_t s; + compat_uptr_t p; + int err; + + err = get_user(i, &map32->version); + if (err || i != 0) + return -EINVAL; + + err = put_user(i, &map->version); + err |= get_user(i, &map32->m.fd); + err |= put_user(i, &map->m.fd); + err |= get_user(i, &map32->m.offset); + err |= put_user(i, &map->m.offset); + err |= get_user(u, &map32->m.flags); + err |= put_user(u, &map->m.flags); + err |= get_user(p, &map32->m.vaddrin); + err |= put_user(p, &map->m.vaddrin); + err |= get_user(s, &map32->m.length); + err |= put_user(s, &map->m.length); + err |= get_user(u, &map32->m.attrs); + err |= put_user(u, &map->m.attrs); + + return err; +} + +static int compat_put_fastrpc_ioctl_mem_map( + struct compat_fastrpc_ioctl_mem_map __user *map32, + struct fastrpc_ioctl_mem_map __user *map) +{ + compat_u64 p; + int err; + + err = get_user(p, &map->m.vaddrout); + err |= put_user(p, &map32->m.vaddrout); + + return err; +} + +static int compat_get_fastrpc_ioctl_mem_unmap( + struct compat_fastrpc_ioctl_mem_unmap __user *unmap32, + struct fastrpc_ioctl_mem_unmap __user *unmap) +{ + compat_int_t i; + compat_size_t s; + compat_u64 p; + int err; + + err = get_user(i, &unmap32->version); + if (err || i != 0) + return -EINVAL; + + err = put_user(i, &unmap->version); + err |= get_user(i, &unmap32->um.fd); + err |= put_user(i, &unmap->um.fd); + err |= get_user(p, &unmap32->um.vaddr); + err |= put_user(p, &unmap->um.vaddr); + err |= get_user(s, &unmap32->um.length); + err |= put_user(s, &unmap->um.length); + + return err; +} + static int compat_get_fastrpc_ioctl_mmap( struct compat_fastrpc_ioctl_mmap __user *map32, struct fastrpc_ioctl_mmap __user *map) @@ -661,25 +765,54 @@ static int compat_fastrpc_get_dsp_info(struct file *filp, return err; } -long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) +static inline long compat_fastrpc_mmap_device_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) { int err = 0; - if (!filp->f_op || !filp->f_op->unlocked_ioctl) - return -ENOTTY; - switch (cmd) { - case COMPAT_FASTRPC_IOCTL_INVOKE: - case COMPAT_FASTRPC_IOCTL_INVOKE_FD: - case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: - case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: + case COMPAT_FASTRPC_IOCTL_MEM_MAP: { - return compat_fastrpc_ioctl_invoke(filp, cmd, arg); + struct compat_fastrpc_ioctl_mem_map __user *map32; + struct fastrpc_ioctl_mem_map __user *map; + long ret; + + map32 = compat_ptr(arg); + map = compat_alloc_user_space(sizeof(*map)); + if (map == NULL) + return -EFAULT; + + err = compat_get_fastrpc_ioctl_mem_map(map32, map); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_MAP, + (unsigned long)map); + if (ret) + return ret; + VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map)); + return err; } - case COMPAT_FASTRPC_IOCTL_INVOKE2: + case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: { - return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); + struct compat_fastrpc_ioctl_mem_unmap __user *unmap32; + struct fastrpc_ioctl_mem_unmap __user *unmap; + long ret; + + unmap32 = compat_ptr(arg); + unmap = compat_alloc_user_space(sizeof(*unmap)); + if (unmap == NULL) + return -EFAULT; + + err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_UNMAP, + (unsigned long)unmap); + if (ret) + return ret; + return err; } case COMPAT_FASTRPC_IOCTL_MMAP: { @@ -740,6 +873,31 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP, (unsigned long)unmap); } + default: + return -ENOIOCTLCMD; + } +} + +long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int err = 0; + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + case COMPAT_FASTRPC_IOCTL_INVOKE: + case COMPAT_FASTRPC_IOCTL_INVOKE_FD: + case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: + case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: + { + return compat_fastrpc_ioctl_invoke(filp, cmd, arg); + } + case COMPAT_FASTRPC_IOCTL_INVOKE2: + { + return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); + } case COMPAT_FASTRPC_IOCTL_MUNMAP_64: { struct compat_fastrpc_ioctl_munmap_64 __user *unmap32; @@ -814,6 +972,16 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, { return compat_fastrpc_get_dsp_info(filp, arg); } + case COMPAT_FASTRPC_IOCTL_MEM_MAP: + /* fall through */ + case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: + /* fall through */ + case COMPAT_FASTRPC_IOCTL_MMAP: + /* fall through */ + case COMPAT_FASTRPC_IOCTL_MMAP_64: + /* fall through */ + case COMPAT_FASTRPC_IOCTL_MUNMAP: + return compat_fastrpc_mmap_device_ioctl(filp, cmd, arg); default: return -ENOIOCTLCMD; } diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index 26853de0ab93..2e33bd5e14a6 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -26,7 +26,8 @@ #define FASTRPC_IOCTL_GET_DSP_INFO \ _IOWR('R', 17, struct fastrpc_ioctl_capability) #define FASTRPC_IOCTL_INVOKE2 _IOWR('R', 18, struct fastrpc_ioctl_invoke2) - +#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 19, struct fastrpc_ioctl_mem_map) +#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 20, struct fastrpc_ioctl_mem_unmap) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" @@ -271,6 +272,77 @@ struct fastrpc_ioctl_munmap_fd { ssize_t len; /* length */ }; +/** + * Control flags for mapping memory on DSP user process + */ +enum fastrpc_map_flags { + /** + * Map memory pages with RW- permission and CACHE WRITEBACK. + * The driver is responsible for cache maintenance when passed + * the buffer to FastRPC calls. Same virtual address will be + * assigned for subsequent FastRPC calls. + */ + FASTRPC_MAP_STATIC = 0, + + /* Reserved */ + FASTRPC_MAP_RESERVED, + + /** + * Map memory pages with RW- permission and CACHE WRITEBACK. + * Mapping tagged with a file descriptor. User is responsible for + * CPU and DSP cache maintenance for the buffer. Get virtual address + * of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() APIs. + */ + FASTRPC_MAP_FD = 2, + + /** + * Mapping delayed until user call HAP_mmap() and HAP_munmap() + * functions on DSP. It is useful to map a buffer with cache modes + * other than default modes. User is responsible for CPU and DSP + * cache maintenance for the buffer. + */ + FASTRPC_MAP_FD_DELAYED, + FASTRPC_MAP_MAX, +}; + +struct fastrpc_mem_map { + int fd; /* ion fd */ + int offset; /* buffer offset */ + uint32_t flags; /* flags defined in enum fastrpc_map_flags */ + int attrs; /* buffer attributes used for SMMU mapping */ + uintptr_t vaddrin; /* buffer virtual address */ + size_t length; /* buffer length */ + uint64_t vaddrout; /* [out] remote virtual address */ +}; + +/* Map and unmap IOCTL methods reserved memory size for future extensions */ +#define MAP_RESERVED_NUM (14) +#define UNMAP_RESERVED_NUM (10) + +/* map memory to DSP device */ +struct fastrpc_ioctl_mem_map { + int version; /* Initial version 0 */ + union { + struct fastrpc_mem_map m; + int reserved[MAP_RESERVED_NUM]; + }; +}; + +struct fastrpc_mem_unmap { + int fd; /* ion fd */ + uint64_t vaddr; /* remote process (dsp) virtual address */ + size_t length; /* buffer size */ +}; + +/* unmap memory to DSP device */ +struct fastrpc_ioctl_mem_unmap { + int version; /* Initial version 0 */ + union { + struct fastrpc_mem_unmap um; + int reserved[UNMAP_RESERVED_NUM]; + }; +}; + struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t data; uint32_t numkeys;