msm: ADSPRPC: Add snapshot of RPC driver

This shapshot was taken as of msm-4.4 commit
("msm: ADSPRPC: Remove obsolete IOMMU domain attribute")

Updated source to fix checkpatch warnings and compilation errors.

Change-Id: Ifb7ed525e1e00226967ed2a2bf1b0ed3765ad5a7
Signed-off-by: Sathish Ambley <sathishambley@codeaurora.org>
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
new file mode 100644
index 0000000..1e5649a
--- /dev/null
+++ b/drivers/char/adsprpc_compat.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/compat.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/msm_ion.h>
+
+#include "adsprpc_compat.h"
+#include "adsprpc_shared.h"
+
+#define COMPAT_FASTRPC_IOCTL_INVOKE \
+		_IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
+#define COMPAT_FASTRPC_IOCTL_MMAP \
+		_IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
+#define COMPAT_FASTRPC_IOCTL_MUNMAP \
+		_IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
+#define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
+		_IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
+#define COMPAT_FASTRPC_IOCTL_INIT \
+		_IOWR('R', 6, struct compat_fastrpc_ioctl_init)
+#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
+		_IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
+
+struct compat_remote_buf {
+	compat_uptr_t pv;	/* buffer pointer */
+	compat_ssize_t len;	/* length of buffer */
+};
+
+union compat_remote_arg {
+	struct compat_remote_buf buf;
+	compat_uint_t h;
+};
+
+struct compat_fastrpc_ioctl_invoke {
+	compat_uint_t handle;	/* remote handle */
+	compat_uint_t sc;	/* scalars describing the data */
+	compat_uptr_t pra;	/* remote arguments list */
+};
+
+struct compat_fastrpc_ioctl_invoke_fd {
+	struct compat_fastrpc_ioctl_invoke inv;
+	compat_uptr_t fds;	/* fd list */
+};
+
+struct compat_fastrpc_ioctl_invoke_attrs {
+	struct compat_fastrpc_ioctl_invoke inv;
+	compat_uptr_t fds;	/* fd list */
+	compat_uptr_t attrs;	/* attribute list */
+};
+
+struct compat_fastrpc_ioctl_mmap {
+	compat_int_t fd;	/* ion fd */
+	compat_uint_t flags;	/* flags for dsp to map with */
+	compat_uptr_t vaddrin;	/* optional virtual address */
+	compat_ssize_t size;	/* size */
+	compat_uptr_t vaddrout;	/* dsps virtual address */
+};
+
+struct compat_fastrpc_ioctl_munmap {
+	compat_uptr_t vaddrout;	/* address to unmap */
+	compat_ssize_t size;	/* size */
+};
+
+struct compat_fastrpc_ioctl_init {
+	compat_uint_t flags;	/* one of FASTRPC_INIT_* macros */
+	compat_uptr_t file;	/* pointer to elf file */
+	compat_int_t filelen;	/* elf file length */
+	compat_int_t filefd;	/* ION fd for the file */
+	compat_uptr_t mem;	/* mem for the PD */
+	compat_int_t memlen;	/* mem length */
+	compat_int_t memfd;	/* ION fd for the mem */
+};
+
+static int compat_get_fastrpc_ioctl_invoke(
+			struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
+			struct fastrpc_ioctl_invoke_attrs __user **inva,
+			unsigned int cmd)
+{
+	compat_uint_t u, sc;
+	compat_ssize_t s;
+	compat_uptr_t p;
+	struct fastrpc_ioctl_invoke_attrs *inv;
+	union compat_remote_arg *pra32;
+	union remote_arg *pra;
+	int err, len, num, j;
+
+	err = get_user(sc, &inv32->inv.sc);
+	if (err)
+		return err;
+
+	len = REMOTE_SCALARS_LENGTH(sc);
+	VERIFY(err, NULL != (inv = compat_alloc_user_space(
+				sizeof(*inv) + len * sizeof(*pra))));
+	if (err)
+		return -EFAULT;
+
+	pra = (union remote_arg *)(inv + 1);
+	err = put_user(pra, &inv->inv.pra);
+	err |= put_user(sc, &inv->inv.sc);
+	err |= get_user(u, &inv32->inv.handle);
+	err |= put_user(u, &inv->inv.handle);
+	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(sc) + REMOTE_SCALARS_OUTBUFS(sc);
+	for (j = 0; j < num; 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) {
+		err |= get_user(p, &inv32->fds);
+		err |= put_user(p, (compat_uptr_t *)&inv->fds);
+	}
+	err |= put_user(NULL, &inv->attrs);
+	if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) {
+		err |= get_user(p, &inv32->attrs);
+		err |= put_user(p, (compat_uptr_t *)&inv->attrs);
+	}
+
+	*inva = inv;
+	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)
+{
+	compat_uint_t u;
+	compat_int_t i;
+	compat_ssize_t s;
+	compat_uptr_t p;
+	int err;
+
+	err = get_user(i, &map32->fd);
+	err |= put_user(i, &map->fd);
+	err |= get_user(u, &map32->flags);
+	err |= put_user(u, &map->flags);
+	err |= get_user(p, &map32->vaddrin);
+	err |= put_user(p, (uintptr_t *)&map->vaddrin);
+	err |= get_user(s, &map32->size);
+	err |= put_user(s, &map->size);
+
+	return err;
+}
+
+static int compat_put_fastrpc_ioctl_mmap(
+			struct compat_fastrpc_ioctl_mmap __user *map32,
+			struct fastrpc_ioctl_mmap __user *map)
+{
+	compat_uptr_t p;
+	int err;
+
+	err = get_user(p, &map->vaddrout);
+	err |= put_user(p, &map32->vaddrout);
+
+	return err;
+}
+
+static int compat_get_fastrpc_ioctl_munmap(
+			struct compat_fastrpc_ioctl_munmap __user *unmap32,
+			struct fastrpc_ioctl_munmap __user *unmap)
+{
+	compat_uptr_t p;
+	compat_ssize_t s;
+	int err;
+
+	err = get_user(p, &unmap32->vaddrout);
+	err |= put_user(p, &unmap->vaddrout);
+	err |= get_user(s, &unmap32->size);
+	err |= put_user(s, &unmap->size);
+
+	return err;
+}
+
+static int compat_get_fastrpc_ioctl_init(
+			struct compat_fastrpc_ioctl_init __user *init32,
+			struct fastrpc_ioctl_init __user *init)
+{
+	compat_uint_t u;
+	compat_uptr_t p;
+	compat_int_t i;
+	int err;
+
+	err = get_user(u, &init32->flags);
+	err |= put_user(u, &init->flags);
+	err |= get_user(p, &init32->file);
+	err |= put_user(p, &init->file);
+	err |= get_user(i, &init32->filelen);
+	err |= put_user(i, &init->filelen);
+	err |= get_user(i, &init32->filefd);
+	err |= put_user(i, &init->filefd);
+	err |= get_user(p, &init32->mem);
+	err |= put_user(p, &init->mem);
+	err |= get_user(i, &init32->memlen);
+	err |= put_user(i, &init->memlen);
+	err |= get_user(i, &init32->memfd);
+	err |= put_user(i, &init->memfd);
+
+	return err;
+}
+
+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:
+	{
+		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,
+				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:
+	{
+		struct compat_fastrpc_ioctl_mmap __user *map32;
+		struct fastrpc_ioctl_mmap __user *map;
+		long ret;
+
+		map32 = compat_ptr(arg);
+		VERIFY(err, NULL != (map = compat_alloc_user_space(
+							sizeof(*map))));
+		if (err)
+			return -EFAULT;
+		VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
+		if (err)
+			return err;
+		ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP,
+							(unsigned long)map);
+		if (ret)
+			return ret;
+		VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
+		return err;
+	}
+	case COMPAT_FASTRPC_IOCTL_MUNMAP:
+	{
+		struct compat_fastrpc_ioctl_munmap __user *unmap32;
+		struct fastrpc_ioctl_munmap __user *unmap;
+
+		unmap32 = compat_ptr(arg);
+		VERIFY(err, NULL != (unmap = compat_alloc_user_space(
+							sizeof(*unmap))));
+		if (err)
+			return -EFAULT;
+		VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
+							unmap));
+		if (err)
+			return err;
+		return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP,
+							(unsigned long)unmap);
+	}
+	case COMPAT_FASTRPC_IOCTL_INIT:
+	{
+		struct compat_fastrpc_ioctl_init __user *init32;
+		struct fastrpc_ioctl_init __user *init;
+
+		init32 = compat_ptr(arg);
+		VERIFY(err, NULL != (init = compat_alloc_user_space(
+							sizeof(*init))));
+		if (err)
+			return -EFAULT;
+		VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
+							init));
+		if (err)
+			return err;
+		return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_INIT,
+							(unsigned long)init);
+	}
+	case FASTRPC_IOCTL_GETINFO:
+	{
+		compat_uptr_t __user *info32;
+		uint32_t __user *info;
+		compat_uint_t u;
+		long ret;
+
+		info32 = compat_ptr(arg);
+		VERIFY(err, NULL != (info = compat_alloc_user_space(
+							sizeof(*info))));
+		if (err)
+			return -EFAULT;
+		ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO,
+							(unsigned long)info);
+		if (ret)
+			return ret;
+		err = get_user(u, info);
+		err |= put_user(u, info32);
+		return err;
+	}
+	case FASTRPC_IOCTL_SETMODE:
+		return filp->f_op->unlocked_ioctl(filp, cmd,
+						(unsigned long)compat_ptr(arg));
+	default:
+		return -ENOIOCTLCMD;
+	}
+}