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

Commit 98fa1b3f authored by Himateja Reddy's avatar Himateja Reddy Committed by Gerrit - the friendly Code Review server
Browse files

msm:ADSPRPC: memory map updates to remote process



New version of interface for mapping and unmapping buffer
to remote process on DSP with additional mapping control flags.
All mappings of user allocated memory are tagged with file descriptor.

Change-Id: I2fb20df3f39476f92dbe0a6ec10e0b6065f90749
Acked-by: default avatarViswanatham Paduchuri <vpaduchu@qti.qualcomm.com>
Signed-off-by: default avatarHimateja Reddy <hmreddy@codeaurora.org>
parent 4c36c737
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;