android_kernel_samsung_msm8976/drivers/staging/android/ion/msm/compat_msm_ion.c

158 lines
4.0 KiB
C

/* Copyright (c) 2014, 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/ion.h>
#include <linux/msm_ion.h>
#include <linux/uaccess.h>
#include "../ion_priv.h"
#include "../compat_ion.h"
struct compat_ion_flush_data {
compat_ion_user_handle_t handle;
compat_int_t fd;
compat_uptr_t vaddr;
compat_uint_t offset;
compat_uint_t length;
};
struct compat_ion_prefetch_data {
compat_int_t heap_id;
compat_ulong_t len;
};
#define COMPAT_ION_IOC_CLEAN_CACHES _IOWR(ION_IOC_MSM_MAGIC, 0, \
struct compat_ion_flush_data)
#define COMPAT_ION_IOC_INV_CACHES _IOWR(ION_IOC_MSM_MAGIC, 1, \
struct compat_ion_flush_data)
#define COMPAT_ION_IOC_CLEAN_INV_CACHES _IOWR(ION_IOC_MSM_MAGIC, 2, \
struct compat_ion_flush_data)
#define COMPAT_ION_IOC_PREFETCH _IOWR(ION_IOC_MSM_MAGIC, 3, \
struct compat_ion_prefetch_data)
#define COMPAT_ION_IOC_DRAIN _IOWR(ION_IOC_MSM_MAGIC, 4, \
struct compat_ion_prefetch_data)
static int compat_get_ion_flush_data(
struct compat_ion_flush_data __user *data32,
struct ion_flush_data __user *data)
{
compat_ion_user_handle_t h;
compat_int_t i;
compat_uptr_t u;
compat_ulong_t l;
int err;
err = get_user(h, &data32->handle);
err |= put_user(h, &data->handle);
err |= get_user(i, &data32->fd);
err |= put_user(i, &data->fd);
err |= get_user(u, &data32->vaddr);
/* upper bits won't get set, zero them */
err |= put_user(NULL, &data->vaddr);
err |= put_user(u, (compat_uptr_t *)&data->vaddr);
err |= get_user(l, &data32->offset);
err |= put_user(l, &data->offset);
err |= get_user(l, &data32->length);
err |= put_user(l, &data->length);
return err;
}
static int compat_get_ion_prefetch_data(
struct compat_ion_prefetch_data __user *data32,
struct ion_prefetch_data __user *data)
{
compat_int_t i;
compat_ulong_t l;
int err;
err = get_user(i, &data32->heap_id);
err |= put_user(i, &data->heap_id);
err |= get_user(l, &data32->len);
err |= put_user(l, &data->len);
return err;
}
static unsigned int convert_cmd(unsigned int cmd)
{
switch (cmd) {
case COMPAT_ION_IOC_CLEAN_CACHES:
return ION_IOC_CLEAN_CACHES;
case COMPAT_ION_IOC_INV_CACHES:
return ION_IOC_INV_CACHES;
case COMPAT_ION_IOC_CLEAN_INV_CACHES:
return ION_IOC_CLEAN_INV_CACHES;
case COMPAT_ION_IOC_PREFETCH:
return ION_IOC_PREFETCH;
case COMPAT_ION_IOC_DRAIN:
return ION_IOC_DRAIN;
default:
return cmd;
}
}
long compat_msm_ion_ioctl(struct ion_client *client, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
case COMPAT_ION_IOC_CLEAN_CACHES:
case COMPAT_ION_IOC_INV_CACHES:
case COMPAT_ION_IOC_CLEAN_INV_CACHES:
{
struct compat_ion_flush_data __user *data32;
struct ion_flush_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_flush_data(data32, data);
if (err)
return err;
return msm_ion_custom_ioctl(client, convert_cmd(cmd),
(unsigned long)data);
}
case COMPAT_ION_IOC_PREFETCH:
case COMPAT_ION_IOC_DRAIN:
{
struct compat_ion_prefetch_data __user *data32;
struct ion_prefetch_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_prefetch_data(data32, data);
if (err)
return err;
return msm_ion_custom_ioctl(client, convert_cmd(cmd),
(unsigned long)data);
}
default:
if (is_compat_task())
return -ENOIOCTLCMD;
else
return msm_ion_custom_ioctl(client, cmd, arg);
}
}