Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0070b55b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm:ADSPRPC: memory map updates to remote process"

parents bfc032ea 98fa1b3f
Loading
Loading
Loading
Loading
+345 −77
Original line number Diff line number Diff line
@@ -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 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
	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 @@ static int fastrpc_internal_munmap_fd(struct fastrpc_file *fl,
	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,11 +4941,10 @@ static int fastrpc_get_dsp_info(
	return err;
}

static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
				 unsigned long ioctl_param)
{
	union {
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;
@@ -4750,11 +4955,116 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
	struct fastrpc_ioctl_control cp;
	struct fastrpc_ioctl_capability cap;
	struct fastrpc_ioctl_invoke2 inv2;
	} p;
};

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_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);
+180 −12
Original line number Diff line number Diff line
@@ -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;
	}
+73 −1
Original line number Diff line number Diff line
@@ -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;