You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
588 lines
16 KiB
588 lines
16 KiB
/*
|
|
* Copyright (c) 2014-2019, 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)
|
|
#define COMPAT_FASTRPC_IOCTL_GETPERF \
|
|
_IOWR('R', 9, struct compat_fastrpc_ioctl_perf)
|
|
#define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
|
|
_IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
|
|
#define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
|
|
_IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
|
|
#define COMPAT_FASTRPC_IOCTL_CONTROL \
|
|
_IOWR('R', 12, struct compat_fastrpc_ioctl_control)
|
|
#define COMPAT_FASTRPC_IOCTL_MMAP_64 \
|
|
_IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
|
|
#define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
|
|
_IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
|
|
|
|
struct compat_remote_buf {
|
|
compat_uptr_t pv; /* buffer pointer */
|
|
compat_size_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_invoke_crc {
|
|
struct compat_fastrpc_ioctl_invoke inv;
|
|
compat_uptr_t fds; /* fd list */
|
|
compat_uptr_t attrs; /* attribute list */
|
|
compat_uptr_t crc; /* crc 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_size_t size; /* size */
|
|
compat_uptr_t vaddrout; /* dsps virtual address */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_mmap_64 {
|
|
compat_int_t fd; /* ion fd */
|
|
compat_uint_t flags; /* flags for dsp to map with */
|
|
compat_u64 vaddrin; /* optional virtual address */
|
|
compat_size_t size; /* size */
|
|
compat_u64 vaddrout; /* dsps virtual address */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_munmap {
|
|
compat_uptr_t vaddrout; /* address to unmap */
|
|
compat_size_t size; /* size */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_munmap_64 {
|
|
compat_u64 vaddrout; /* address to unmap */
|
|
compat_size_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 */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_init_attrs {
|
|
struct compat_fastrpc_ioctl_init init;
|
|
compat_int_t attrs; /* attributes to init process */
|
|
compat_int_t siglen; /* test signature file length */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_perf { /* kernel performance data */
|
|
compat_uptr_t data;
|
|
compat_int_t numkeys;
|
|
compat_uptr_t keys;
|
|
};
|
|
|
|
#define FASTRPC_CONTROL_LATENCY (1)
|
|
struct compat_fastrpc_ctrl_latency {
|
|
compat_uint_t enable; /* latency control enable */
|
|
compat_uint_t level; /* level of control */
|
|
};
|
|
|
|
#define FASTRPC_CONTROL_KALLOC (3)
|
|
struct compat_fastrpc_ctrl_kalloc {
|
|
compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
|
|
};
|
|
|
|
struct compat_fastrpc_ioctl_control {
|
|
compat_uint_t req;
|
|
union {
|
|
struct compat_fastrpc_ctrl_latency lp;
|
|
struct compat_fastrpc_ctrl_kalloc kalloc;
|
|
};
|
|
};
|
|
|
|
static int compat_get_fastrpc_ioctl_invoke(
|
|
struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
|
|
struct fastrpc_ioctl_invoke_crc __user **inva,
|
|
unsigned int cmd)
|
|
{
|
|
compat_uint_t u, sc;
|
|
compat_size_t s;
|
|
compat_uptr_t p;
|
|
struct fastrpc_ioctl_invoke_crc *inv;
|
|
union compat_remote_arg *pra32;
|
|
union remote_arg *pra;
|
|
int err, len, 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);
|
|
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);
|
|
}
|
|
|
|
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) ||
|
|
(cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC)) {
|
|
err |= get_user(p, &inv32->attrs);
|
|
err |= put_user(p, (compat_uptr_t *)&inv->attrs);
|
|
}
|
|
err |= put_user(NULL, (compat_uptr_t __user **)&inv->crc);
|
|
if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) {
|
|
err |= get_user(p, &inv32->crc);
|
|
err |= put_user(p, (compat_uptr_t __user *)&inv->crc);
|
|
}
|
|
|
|
*inva = inv;
|
|
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_size_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_get_fastrpc_ioctl_mmap_64(
|
|
struct compat_fastrpc_ioctl_mmap_64 __user *map32,
|
|
struct fastrpc_ioctl_mmap __user *map)
|
|
{
|
|
compat_uint_t u;
|
|
compat_int_t i;
|
|
compat_size_t s;
|
|
compat_u64 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, &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_put_fastrpc_ioctl_mmap_64(
|
|
struct compat_fastrpc_ioctl_mmap_64 __user *map32,
|
|
struct fastrpc_ioctl_mmap __user *map)
|
|
{
|
|
compat_u64 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_size_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_munmap_64(
|
|
struct compat_fastrpc_ioctl_munmap_64 __user *unmap32,
|
|
struct fastrpc_ioctl_munmap __user *unmap)
|
|
{
|
|
compat_u64 p;
|
|
compat_size_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_perf(
|
|
struct compat_fastrpc_ioctl_perf __user *perf32,
|
|
struct fastrpc_ioctl_perf __user *perf)
|
|
{
|
|
compat_uptr_t p;
|
|
int err;
|
|
|
|
err = get_user(p, &perf32->data);
|
|
err |= put_user(p, &perf->data);
|
|
err |= get_user(p, &perf32->keys);
|
|
err |= put_user(p, &perf->keys);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int compat_get_fastrpc_ioctl_control(
|
|
struct compat_fastrpc_ioctl_control __user *ctrl32,
|
|
struct fastrpc_ioctl_control __user *ctrl)
|
|
{
|
|
compat_uptr_t p;
|
|
int err;
|
|
|
|
err = get_user(p, &ctrl32->req);
|
|
err |= put_user(p, &ctrl->req);
|
|
if (p == FASTRPC_CONTROL_LATENCY) {
|
|
err |= get_user(p, &ctrl32->lp.enable);
|
|
err |= put_user(p, &ctrl->lp.enable);
|
|
err |= get_user(p, &ctrl32->lp.level);
|
|
err |= put_user(p, &ctrl->lp.level);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int compat_get_fastrpc_ioctl_init(
|
|
struct compat_fastrpc_ioctl_init_attrs __user *init32,
|
|
struct fastrpc_ioctl_init_attrs __user *init,
|
|
unsigned int cmd)
|
|
{
|
|
compat_uint_t u;
|
|
compat_uptr_t p;
|
|
compat_int_t i;
|
|
int err;
|
|
|
|
err = get_user(u, &init32->init.flags);
|
|
err |= put_user(u, &init->init.flags);
|
|
err |= get_user(p, &init32->init.file);
|
|
err |= put_user(p, &init->init.file);
|
|
err |= get_user(i, &init32->init.filelen);
|
|
err |= put_user(i, &init->init.filelen);
|
|
err |= get_user(i, &init32->init.filefd);
|
|
err |= put_user(i, &init->init.filefd);
|
|
err |= get_user(p, &init32->init.mem);
|
|
err |= put_user(p, &init->init.mem);
|
|
err |= get_user(i, &init32->init.memlen);
|
|
err |= put_user(i, &init->init.memlen);
|
|
err |= get_user(i, &init32->init.memfd);
|
|
err |= put_user(i, &init->init.memfd);
|
|
|
|
err |= put_user(0, &init->attrs);
|
|
if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
|
|
err |= get_user(i, &init32->attrs);
|
|
err |= put_user(i, (compat_uptr_t *)&init->attrs);
|
|
}
|
|
|
|
err |= put_user(0, &init->siglen);
|
|
if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
|
|
err |= get_user(i, &init32->siglen);
|
|
err |= put_user(i, (compat_uptr_t *)&init->siglen);
|
|
}
|
|
|
|
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:
|
|
case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
|
|
{
|
|
struct compat_fastrpc_ioctl_invoke_crc __user *inv32;
|
|
struct fastrpc_ioctl_invoke_crc __user *inv;
|
|
|
|
inv32 = compat_ptr(arg);
|
|
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
|
|
&inv, cmd));
|
|
if (err)
|
|
return err;
|
|
return filp->f_op->unlocked_ioctl(filp,
|
|
FASTRPC_IOCTL_INVOKE_CRC, (unsigned long)inv);
|
|
}
|
|
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_MMAP_64:
|
|
{
|
|
struct compat_fastrpc_ioctl_mmap_64 __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_64(map32, map));
|
|
if (err)
|
|
return err;
|
|
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP_64,
|
|
(unsigned long)map);
|
|
if (ret)
|
|
return ret;
|
|
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(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_MUNMAP_64:
|
|
{
|
|
struct compat_fastrpc_ioctl_munmap_64 __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_64(unmap32,
|
|
unmap));
|
|
if (err)
|
|
return err;
|
|
return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP_64,
|
|
(unsigned long)unmap);
|
|
}
|
|
case COMPAT_FASTRPC_IOCTL_INIT:
|
|
/* fall through */
|
|
case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
|
|
{
|
|
struct compat_fastrpc_ioctl_init_attrs __user *init32;
|
|
struct fastrpc_ioctl_init_attrs __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, cmd));
|
|
if (err)
|
|
return err;
|
|
return filp->f_op->unlocked_ioctl(filp,
|
|
FASTRPC_IOCTL_INIT_ATTRS, (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;
|
|
err = get_user(u, info32);
|
|
err |= put_user(u, info);
|
|
if (err)
|
|
return err;
|
|
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));
|
|
case COMPAT_FASTRPC_IOCTL_CONTROL:
|
|
{
|
|
struct compat_fastrpc_ioctl_control __user *ctrl32;
|
|
struct fastrpc_ioctl_control __user *ctrl;
|
|
compat_uptr_t p;
|
|
|
|
ctrl32 = compat_ptr(arg);
|
|
VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
|
|
sizeof(*ctrl))));
|
|
if (err)
|
|
return -EFAULT;
|
|
VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
|
|
ctrl));
|
|
if (err)
|
|
return err;
|
|
err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
|
|
(unsigned long)ctrl);
|
|
if (err)
|
|
return err;
|
|
err = get_user(p, &ctrl32->req);
|
|
if (err)
|
|
return err;
|
|
if (p == FASTRPC_CONTROL_KALLOC) {
|
|
err = get_user(p, &ctrl->kalloc.kalloc_support);
|
|
err |= put_user(p, &ctrl32->kalloc.kalloc_support);
|
|
}
|
|
return err;
|
|
}
|
|
case COMPAT_FASTRPC_IOCTL_GETPERF:
|
|
{
|
|
struct compat_fastrpc_ioctl_perf __user *perf32;
|
|
struct fastrpc_ioctl_perf *perf;
|
|
compat_uint_t u;
|
|
long ret;
|
|
|
|
perf32 = compat_ptr(arg);
|
|
VERIFY(err, NULL != (perf = compat_alloc_user_space(
|
|
sizeof(*perf))));
|
|
if (err)
|
|
return -EFAULT;
|
|
VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
|
|
perf));
|
|
if (err)
|
|
return err;
|
|
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
|
|
(unsigned long)perf);
|
|
if (ret)
|
|
return ret;
|
|
err = get_user(u, &perf->numkeys);
|
|
err |= put_user(u, &perf32->numkeys);
|
|
return err;
|
|
}
|
|
default:
|
|
return -ENOIOCTLCMD;
|
|
}
|
|
}
|
|
|