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

Commit 58dc64d1 authored by Sathish Ambley's avatar Sathish Ambley
Browse files

msm: ADSPRPC: Support handles being passed in the invocation



Handles can now be passed in the RPC invocations which would
bypass the cache operations and send the pages over to the remote
subsystem for it to map locally.

Change-Id: If205221f4c91874f3fbae85a2e813c3a99fee0bf
Signed-off-by: default avatarSathish Ambley <sathishambley@codeaurora.org>
parent ecf596b7
Loading
Loading
Loading
Loading
+51 −28
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#define BALIGN		128
#define NUM_CHANNELS	4	/* adsp, mdsp, slpi, cdsp*/
#define NUM_SESSIONS	9	/*8 compute, 1 cpz*/
#define M_FDLIST	16

#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)

@@ -429,7 +430,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
		ion_free(fl->apps->client, map->handle);
	if (sess->smmu.enabled) {
		if (map->size || map->phys)
			msm_dma_unmap_sg(fl->sctx->dev,
			msm_dma_unmap_sg(sess->dev,
				map->table->sgl,
				map->table->nents, DMA_BIDIRECTIONAL,
				map->buf);
@@ -926,12 +927,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
	uint32_t sc = ctx->sc;
	int inbufs = REMOTE_SCALARS_INBUFS(sc);
	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
	int bufs = inbufs + outbufs;
	int handles, bufs = inbufs + outbufs;
	uintptr_t args;
	ssize_t rlen = 0, copylen = 0, metalen = 0;
	int i, inh, oix;
	int i, oix;
	int err = 0;
	int mflags = 0;
	uint64_t *fdlist;

	/* calculate size of the metadata */
	rpra = 0;
@@ -949,7 +951,15 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
					mflags, &ctx->maps[i]);
		ipage += 1;
	}
	metalen = copylen = (ssize_t)&ipage[0];
	handles = REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc);
	for (i = bufs; i < bufs + handles; i++) {
		VERIFY(err, !fastrpc_mmap_create(ctx->fl, ctx->fds[i],
				FASTRPC_ATTR_NOVA, 0, 0, 0, &ctx->maps[i]));
		if (err)
			goto bail;
		ipage += 1;
	}
	metalen = copylen = (ssize_t)&ipage[0] + (sizeof(uint64_t) * M_FDLIST);
	/* calculate len requreed for copying */
	for (oix = 0; oix < inbufs + outbufs; ++oix) {
		int i = ctx->overps[oix]->raix;
@@ -978,14 +988,11 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
	pages = smq_phy_page_start(sc, list);
	ipage = pages;
	args = (uintptr_t)ctx->buf->virt + metalen;
	for (i = 0; i < bufs; ++i) {
		ssize_t len = lpra[i].buf.len;

		list[i].num = 0;
		list[i].pgidx = 0;
		if (!len)
			continue;
	for (i = 0; i < bufs + handles; ++i) {
		if (lpra[i].buf.len)
			list[i].num = 1;
		else
			list[i].num = 0;
		list[i].pgidx = ipage - pages;
		ipage++;
	}
@@ -1006,7 +1013,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
			int idx = list[i].pgidx;

			if (map->attr & FASTRPC_ATTR_NOVA) {
				offset = (uintptr_t)lpra[i].buf.pv;
				offset = 0;
			} else {
				down_read(&current->mm->mmap_sem);
				VERIFY(err, NULL != (vma = find_vma(current->mm,
@@ -1026,6 +1033,15 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
		}
		rpra[i].buf.pv = buf;
	}
	for (i = bufs; i < bufs + handles; ++i) {
		struct fastrpc_mmap *map = ctx->maps[i];

		pages[i].addr = map->phys;
		pages[i].size = map->size;
	}
	fdlist = (uint64_t *)&pages[bufs + handles];
	for (i = 0; i < M_FDLIST; i++)
		fdlist[i] = 0;
	/* copy non ion buffers */
	rlen = copylen - metalen;
	for (oix = 0; oix < inbufs + outbufs; ++oix) {
@@ -1076,11 +1092,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
			dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
			uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
	}
	inh = inbufs + outbufs;
	for (i = 0; i < REMOTE_SCALARS_INHANDLES(sc); i++) {
		rpra[inh + i].buf.pv = ptr_to_uint64(ctx->lpra[inh + i].buf.pv);
		rpra[inh + i].buf.len = ctx->lpra[inh + i].buf.len;
		rpra[inh + i].h = ctx->lpra[inh + i].h;
	for (i = bufs; i < bufs + handles; i++) {
		rpra[i].dma.fd = ctx->fds[i];
		rpra[i].dma.len = (uint32_t)lpra[i].buf.len;
		rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv;
	}
	if (!ctx->fl->sctx->smmu.coherent)
		dmac_flush_range((char *)rpra, (char *)rpra + ctx->used);
@@ -1092,12 +1107,20 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
		    remote_arg_t *upra)
{
	uint32_t sc = ctx->sc;
	struct smq_invoke_buf *list;
	struct smq_phy_page *pages;
	struct fastrpc_mmap *mmap;
	uint64_t *fdlist;
	remote_arg64_t *rpra = ctx->rpra;
	int i, inbufs, outbufs, outh, size;
	int i, inbufs, outbufs, handles;
	int err = 0;

	inbufs = REMOTE_SCALARS_INBUFS(sc);
	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
	handles = REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc);
	list = smq_invoke_buf_start(ctx->rpra, sc);
	pages = smq_phy_page_start(sc, list);
	fdlist = (uint64_t *)(pages + inbufs + outbufs + handles);
	for (i = inbufs; i < inbufs + outbufs; ++i) {
		if (!ctx->maps[i]) {
			K_COPY_TO_USER(err, kernel,
@@ -1111,12 +1134,14 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
			ctx->maps[i] = 0;
		}
	}
	size = sizeof(*rpra) * REMOTE_SCALARS_OUTHANDLES(sc);
	if (size) {
		outh = inbufs + outbufs + REMOTE_SCALARS_INHANDLES(sc);
		K_COPY_TO_USER(err, kernel, &upra[outh], &rpra[outh], size);
		if (err)
			goto bail;
	if (inbufs + outbufs + handles) {
		for (i = 0; i < M_FDLIST; i++) {
			if (!fdlist[i])
				break;
			if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0,
						0, &mmap))
				fastrpc_mmap_free(mmap);
		}
	}
 bail:
	return err;
@@ -1158,7 +1183,6 @@ static void inv_args(struct smq_invoke_ctx *ctx)
	uint32_t sc = ctx->sc;
	remote_arg64_t *rpra = ctx->rpra;
	int used = ctx->used;
	int inv = 0;

	inbufs = REMOTE_SCALARS_INBUFS(sc);
	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
@@ -1171,7 +1195,6 @@ static void inv_args(struct smq_invoke_ctx *ctx)
			continue;
		if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
				buf_page_start(rpra[i].buf.pv)) {
			inv = 1;
			continue;
		}
		if (map && map->handle)
@@ -1184,7 +1207,7 @@ static void inv_args(struct smq_invoke_ctx *ctx)
						 + rpra[i].buf.len));
	}

	if (inv || REMOTE_SCALARS_OUTHANDLES(sc))
	if (rpra)
		dmac_inv_range(rpra, (char *)rpra + used);
}

+3 −40
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static int compat_get_fastrpc_ioctl_invoke(
	struct fastrpc_ioctl_invoke_attrs *inv;
	union compat_remote_arg *pra32;
	union remote_arg *pra;
	int err, len, num, j;
	int err, len, j;

	err = get_user(sc, &inv32->inv.sc);
	if (err)
@@ -117,17 +117,12 @@ static int compat_get_fastrpc_ioctl_invoke(

	pra32 = compat_ptr(p);
	pra = (union remote_arg *)(inv + 1);
	num = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
	for (j = 0; j < num; j++) {
	for (j = 0; j < len; j++) {
		err |= get_user(p, &pra32[j].buf.pv);
		err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
		err |= get_user(s, &pra32[j].buf.len);
		err |= put_user(s, &pra[j].buf.len);
	}
	for (j = 0; j < REMOTE_SCALARS_INHANDLES(sc); j++) {
		err |= get_user(u, &pra32[num + j].h);
		err |= put_user(u, &pra[num + j].h);
	}

	err |= put_user(NULL, &inv->fds);
	if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
@@ -144,33 +139,6 @@ static int compat_get_fastrpc_ioctl_invoke(
	return err;
}

static int compat_put_fastrpc_ioctl_invoke(
			struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
			struct fastrpc_ioctl_invoke_attrs __user *inv)
{
	compat_uptr_t p;
	compat_uint_t u, h;
	union compat_remote_arg *pra32;
	union remote_arg *pra;
	int err, i, num;

	err = get_user(u, &inv32->inv.sc);
	err |= get_user(p, &inv32->inv.pra);
	if (err)
		return err;

	pra32 = compat_ptr(p);
	pra = (union remote_arg *)(inv + 1);
	num = REMOTE_SCALARS_INBUFS(u) + REMOTE_SCALARS_OUTBUFS(u)
		+ REMOTE_SCALARS_INHANDLES(u);
	for (i = 0;  i < REMOTE_SCALARS_OUTHANDLES(u); i++) {
		err |= get_user(h, &pra[num + i].h);
		err |= put_user(h, &pra32[num + i].h);
	}

	return err;
}

static int compat_get_fastrpc_ioctl_mmap(
			struct compat_fastrpc_ioctl_mmap __user *map32,
			struct fastrpc_ioctl_mmap __user *map)
@@ -264,19 +232,14 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
	{
		struct compat_fastrpc_ioctl_invoke_attrs __user *inv32;
		struct fastrpc_ioctl_invoke_attrs __user *inv;
		long ret;

		inv32 = compat_ptr(arg);
		VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
							&inv, cmd));
		if (err)
			return err;
		ret = filp->f_op->unlocked_ioctl(filp,
		return filp->f_op->unlocked_ioctl(filp,
				FASTRPC_IOCTL_INVOKE_ATTRS, (unsigned long)inv);
		if (ret)
			return ret;
		VERIFY(err, 0 == compat_put_fastrpc_ioctl_invoke(inv32, inv));
		return err;
	}
	case COMPAT_FASTRPC_IOCTL_MMAP:
	{
+14 −1
Original line number Diff line number Diff line
@@ -104,8 +104,15 @@ struct remote_buf64 {
	int64_t len;
};

struct remote_dma_handle64 {
	int fd;
	uint32_t offset;
	uint32_t len;
};

union remote_arg64 {
	struct remote_buf64	buf;
	struct remote_dma_handle64 dma;
	uint32_t h;
};

@@ -116,8 +123,14 @@ struct remote_buf {
	ssize_t len;		/* length of buffer */
};

struct remote_dma_handle {
	int fd;
	uint32_t offset;
};

union remote_arg {
	struct remote_buf buf;	/* buffer info */
	struct remote_dma_handle dma;
	uint32_t h;		/* remote handle */
};

@@ -205,7 +218,7 @@ static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg64_t *pra,
static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc,
						struct smq_invoke_buf *buf)
{
	int nTotal = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
	int nTotal = REMOTE_SCALARS_LENGTH(sc);

	return (struct smq_phy_page *)(&buf[nTotal]);
}