M7350/qcom-opensource/kernel/kernel-tests/ion/compat_msm_ion_test_module.c
2024-09-09 08:57:42 +00:00

219 lines
5.4 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/uaccess.h>
#include "iontest.h"
struct compat_ion_test_data {
compat_uint_t align;
compat_uint_t size;
compat_uint_t heap_type_req;
compat_ulong_t heap_id_mask;
compat_ulong_t flags;
compat_ulong_t vaddr;
compat_ulong_t cache;
compat_int_t shared_fd;
compat_uint_t valid;
};
struct compat_ion_heap_data {
compat_int_t type;
compat_uint_t size;
compat_ulong_t heap_id_mask;
compat_uint_t valid;
};
#define COMPAT_IOC_ION_KALLOC _IOW(MSM_ION_MAGIC, 2, \
struct compat_ion_test_data)
#define COMPAT_IOC_ION_UIMPORT _IOW(MSM_ION_MAGIC, 7, \
struct compat_ion_test_data)
#define COMPAT_IOC_ION_UBUF_FLAGS _IOR(MSM_ION_MAGIC, 10, \
compat_ulong_t)
#define COMPAT_IOC_ION_UBUF_SIZE _IOR(MSM_ION_MAGIC, 11, \
compat_ulong_t)
#define COMPAT_IOC_ION_FIND_PROPER_HEAP _IOWR(MSM_ION_MAGIC, 14, \
struct compat_ion_heap_data)
static int compat_get_ion_test_data(
struct compat_ion_test_data __user *data32,
struct ion_test_data __user *data)
{
compat_int_t i;
compat_uint_t u;
compat_ulong_t l;
int err;
err = get_user(u, &data32->align);
err |= put_user(u, &data->align);
err |= get_user(u, &data32->size);
err |= put_user(u, &data->size);
err |= get_user(u, &data32->heap_type_req);
err |= put_user(u, &data->heap_type_req);
err |= get_user(l, &data32->heap_id_mask);
err |= put_user(l, &data->heap_id_mask);
err |= get_user(l, &data32->flags);
err |= put_user(l, &data->flags);
err |= get_user(l, &data32->vaddr);
err |= put_user(l, &data->vaddr);
err |= get_user(l, &data32->cache);
err |= put_user(l, &data->cache);
err |= get_user(i, &data32->shared_fd);
err |= put_user(i, &data->shared_fd);
err |= get_user(u, &data32->valid);
err |= put_user(u, &data->valid);
return err;
}
static int compat_get_ion_heap_data(
struct compat_ion_heap_data __user *data32,
struct ion_heap_data __user *data)
{
compat_int_t i;
compat_uint_t u;
compat_ulong_t l;
int err;
err = get_user(i, &data32->type);
err |= put_user(i, &data->type);
err |= get_user(u, &data32->size);
err |= put_user(u, &data->size);
err |= get_user(l, &data32->heap_id_mask);
err |= put_user(l, &data->heap_id_mask);
err |= get_user(u, &data32->valid);
err |= put_user(u, &data->valid);
return err;
}
static int compat_put_ion_heap_data(
struct compat_ion_heap_data __user *data32,
struct ion_heap_data __user *data)
{
compat_int_t i;
compat_uint_t u;
compat_ulong_t l;
int err;
err = get_user(i, &data->type);
err |= put_user(i, &data32->type);
err |= get_user(u, &data->size);
err |= put_user(u, &data32->size);
err |= get_user(l, &data->heap_id_mask);
err |= put_user(l, &data32->heap_id_mask);
err |= get_user(u, &data->valid);
err |= put_user(u, &data32->valid);
return err;
}
static int compat_put_unsigned_long(compat_ulong_t __user *data32,
unsigned long __user *data)
{
compat_ulong_t l;
int err;
err = get_user(l, data);
err |= put_user(l, data32);
return err;
}
static unsigned convert_cmd(unsigned cmd)
{
switch(cmd) {
case COMPAT_IOC_ION_KALLOC:
return IOC_ION_KALLOC;
case COMPAT_IOC_ION_UIMPORT:
return IOC_ION_KALLOC;
case COMPAT_IOC_ION_UBUF_FLAGS:
return IOC_ION_UBUF_FLAGS;
case COMPAT_IOC_ION_UBUF_SIZE:
return IOC_ION_UBUF_SIZE;
case COMPAT_IOC_ION_FIND_PROPER_HEAP:
return IOC_ION_FIND_PROPER_HEAP;
default:
return cmd;
}
}
long compat_ion_test_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
long ret;
switch(cmd) {
case COMPAT_IOC_ION_UIMPORT:
case COMPAT_IOC_ION_KALLOC: {
struct compat_ion_test_data __user *data32;
struct ion_test_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_test_data(data32, data);
if (err)
return err;
return file->f_op->unlocked_ioctl(file, convert_cmd(cmd),
(unsigned long)data);
}
case COMPAT_IOC_ION_UBUF_SIZE:
case COMPAT_IOC_ION_UBUF_FLAGS: {
compat_ulong_t __user *data32;
unsigned long __user *data;
int err;
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
if (data == NULL)
return -EFAULT;
ret = file->f_op->unlocked_ioctl(file, convert_cmd(cmd),
(unsigned long)data);
err = compat_put_unsigned_long(data32, data);
return ret ? ret : err;
}
case COMPAT_IOC_ION_FIND_PROPER_HEAP: {
struct compat_ion_heap_data __user *data32;
struct ion_heap_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_heap_data(data32, data);
if (err)
return err;
ret = file->f_op->unlocked_ioctl(file, convert_cmd(cmd),
(unsigned long)data);
err = compat_put_ion_heap_data(data32, data);
return ret ? ret : err;
}
default:
return file->f_op->unlocked_ioctl(file, cmd,
(unsigned long)compat_ptr(arg));
}
}