Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / android / ion / compat_ion.c
diff --git a/kernel/drivers/staging/android/ion/compat_ion.c b/kernel/drivers/staging/android/ion/compat_ion.c
new file mode 100644 (file)
index 0000000..a402fda
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * drivers/staging/android/ion/compat_ion.c
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "ion.h"
+#include "compat_ion.h"
+
+/* See drivers/staging/android/uapi/ion.h for the definition of these structs */
+struct compat_ion_allocation_data {
+       compat_size_t len;
+       compat_size_t align;
+       compat_uint_t heap_id_mask;
+       compat_uint_t flags;
+       compat_int_t handle;
+};
+
+struct compat_ion_custom_data {
+       compat_uint_t cmd;
+       compat_ulong_t arg;
+};
+
+struct compat_ion_handle_data {
+       compat_int_t handle;
+};
+
+#define COMPAT_ION_IOC_ALLOC   _IOWR(ION_IOC_MAGIC, 0, \
+                                     struct compat_ion_allocation_data)
+#define COMPAT_ION_IOC_FREE    _IOWR(ION_IOC_MAGIC, 1, \
+                                     struct compat_ion_handle_data)
+#define COMPAT_ION_IOC_CUSTOM  _IOWR(ION_IOC_MAGIC, 6, \
+                                     struct compat_ion_custom_data)
+
+static int compat_get_ion_allocation_data(
+                       struct compat_ion_allocation_data __user *data32,
+                       struct ion_allocation_data __user *data)
+{
+       compat_size_t s;
+       compat_uint_t u;
+       compat_int_t i;
+       int err;
+
+       err = get_user(s, &data32->len);
+       err |= put_user(s, &data->len);
+       err |= get_user(s, &data32->align);
+       err |= put_user(s, &data->align);
+       err |= get_user(u, &data32->heap_id_mask);
+       err |= put_user(u, &data->heap_id_mask);
+       err |= get_user(u, &data32->flags);
+       err |= put_user(u, &data->flags);
+       err |= get_user(i, &data32->handle);
+       err |= put_user(i, &data->handle);
+
+       return err;
+}
+
+static int compat_get_ion_handle_data(
+                       struct compat_ion_handle_data __user *data32,
+                       struct ion_handle_data __user *data)
+{
+       compat_int_t i;
+       int err;
+
+       err = get_user(i, &data32->handle);
+       err |= put_user(i, &data->handle);
+
+       return err;
+}
+
+static int compat_put_ion_allocation_data(
+                       struct compat_ion_allocation_data __user *data32,
+                       struct ion_allocation_data __user *data)
+{
+       compat_size_t s;
+       compat_uint_t u;
+       compat_int_t i;
+       int err;
+
+       err = get_user(s, &data->len);
+       err |= put_user(s, &data32->len);
+       err |= get_user(s, &data->align);
+       err |= put_user(s, &data32->align);
+       err |= get_user(u, &data->heap_id_mask);
+       err |= put_user(u, &data32->heap_id_mask);
+       err |= get_user(u, &data->flags);
+       err |= put_user(u, &data32->flags);
+       err |= get_user(i, &data->handle);
+       err |= put_user(i, &data32->handle);
+
+       return err;
+}
+
+static int compat_get_ion_custom_data(
+                       struct compat_ion_custom_data __user *data32,
+                       struct ion_custom_data __user *data)
+{
+       compat_uint_t cmd;
+       compat_ulong_t arg;
+       int err;
+
+       err = get_user(cmd, &data32->cmd);
+       err |= put_user(cmd, &data->cmd);
+       err |= get_user(arg, &data32->arg);
+       err |= put_user(arg, &data->arg);
+
+       return err;
+};
+
+long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+
+       if (!filp->f_op->unlocked_ioctl)
+               return -ENOTTY;
+
+       switch (cmd) {
+       case COMPAT_ION_IOC_ALLOC:
+       {
+               struct compat_ion_allocation_data __user *data32;
+               struct ion_allocation_data __user *data;
+               int err;
+
+               data32 = compat_ptr(arg);
+               data = compat_alloc_user_space(sizeof(*data));
+               if (data == NULL)
+                       return -EFAULT;
+
+               err = compat_get_ion_allocation_data(data32, data);
+               if (err)
+                       return err;
+               ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
+                                                       (unsigned long)data);
+               err = compat_put_ion_allocation_data(data32, data);
+               return ret ? ret : err;
+       }
+       case COMPAT_ION_IOC_FREE:
+       {
+               struct compat_ion_handle_data __user *data32;
+               struct ion_handle_data __user *data;
+               int err;
+
+               data32 = compat_ptr(arg);
+               data = compat_alloc_user_space(sizeof(*data));
+               if (data == NULL)
+                       return -EFAULT;
+
+               err = compat_get_ion_handle_data(data32, data);
+               if (err)
+                       return err;
+
+               return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
+                                                       (unsigned long)data);
+       }
+       case COMPAT_ION_IOC_CUSTOM: {
+               struct compat_ion_custom_data __user *data32;
+               struct ion_custom_data __user *data;
+               int err;
+
+               data32 = compat_ptr(arg);
+               data = compat_alloc_user_space(sizeof(*data));
+               if (data == NULL)
+                       return -EFAULT;
+
+               err = compat_get_ion_custom_data(data32, data);
+               if (err)
+                       return err;
+
+               return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
+                                                       (unsigned long)data);
+       }
+       case ION_IOC_SHARE:
+       case ION_IOC_MAP:
+       case ION_IOC_IMPORT:
+       case ION_IOC_SYNC:
+               return filp->f_op->unlocked_ioctl(filp, cmd,
+                                               (unsigned long)compat_ptr(arg));
+       default:
+               return -ENOIOCTLCMD;
+       }
+}