blob: 1b44bb61cc2ccb660937f5b623f3bbc49d532896 [file] [log] [blame]
/*
* Samsung Exynos SoC series VIPx driver
*
* Copyright (c) 2018 Samsung Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/slab.h>
#include "vipx-log.h"
#include "vipx-core.h"
#include "vipx-context.h"
#include "vipx-ioctl.h"
struct vipx_ioc_load_kernel_binary32 {
unsigned int size;
unsigned int global_id;
int kernel_fd;
unsigned int kernel_size;
int ret;
struct compat_timespec timestamp[4];
int reserved[2];
};
struct vipx_ioc_unload_kernel_binary32 {
unsigned int size;
unsigned int global_id;
int kernel_fd;
unsigned int kernel_size;
int ret;
struct compat_timespec timestamp[4];
int reserved[2];
};
struct vipx_ioc_load_graph_info32 {
unsigned int size;
struct vipx_common_graph_info graph_info;
int ret;
struct compat_timespec timestamp[4];
int reserved[2];
};
struct vipx_ioc_unload_graph_info32 {
unsigned int size;
unsigned int graph_id;
int ret;
struct compat_timespec timestamp[4];
int reserved[2];
};
struct vipx_ioc_execute_submodel32 {
unsigned int size;
struct vipx_common_execute_info execute_info;
int ret;
struct compat_timespec timestamp[4];
int reserved[2];
};
#define VIPX_IOC_LOAD_KERNEL_BINARY32 \
_IOWR('V', 0, struct vipx_ioc_load_kernel_binary32)
#define VIPX_IOC_UNLOAD_KERNEL_BINARY32 \
_IOWR('V', 1, struct vipx_ioc_unload_kernel_binary32)
#define VIPX_IOC_LOAD_GRAPH_INFO32 \
_IOWR('V', 2, struct vipx_ioc_load_graph_info32)
#define VIPX_IOC_UNLOAD_GRAPH_INFO32 \
_IOWR('V', 3, struct vipx_ioc_unload_graph_info32)
#define VIPX_IOC_EXECUTE_SUBMODEL32 \
_IOWR('V', 4, struct vipx_ioc_execute_submodel32)
static int __vipx_ioctl_get_load_kernel_binary32(
struct vipx_ioc_load_kernel_binary *karg,
struct vipx_ioc_load_kernel_binary32 __user *uarg)
{
int ret;
vipx_enter();
if (get_user(karg->size, &uarg->size) ||
get_user(karg->global_id, &uarg->global_id) ||
get_user(karg->kernel_fd, &uarg->kernel_fd) ||
get_user(karg->kernel_size, &uarg->kernel_size)) {
ret = -EFAULT;
vipx_err("Copy failed [Load kernel binary(32)]\n");
goto p_err;
}
memset(karg->timestamp, 0, sizeof(karg->timestamp));
memset(karg->reserved, 0, sizeof(karg->reserved));
vipx_leave();
return 0;
p_err:
return ret;
}
static void __vipx_ioctl_put_load_kernel_binary32(
struct vipx_ioc_load_kernel_binary *karg,
struct vipx_ioc_load_kernel_binary32 __user *uarg)
{
vipx_enter();
if (put_user(karg->ret, &uarg->ret) ||
put_user(karg->timestamp[0].tv_sec,
&uarg->timestamp[0].tv_sec) ||
put_user(karg->timestamp[0].tv_nsec,
&uarg->timestamp[0].tv_nsec) ||
put_user(karg->timestamp[1].tv_sec,
&uarg->timestamp[1].tv_sec) ||
put_user(karg->timestamp[1].tv_nsec,
&uarg->timestamp[1].tv_nsec) ||
put_user(karg->timestamp[2].tv_sec,
&uarg->timestamp[2].tv_sec) ||
put_user(karg->timestamp[2].tv_nsec,
&uarg->timestamp[2].tv_nsec) ||
put_user(karg->timestamp[3].tv_sec,
&uarg->timestamp[3].tv_sec) ||
put_user(karg->timestamp[3].tv_nsec,
&uarg->timestamp[3].tv_nsec)) {
vipx_err("Copy failed to user [Load kernel binary(32)]\n");
}
vipx_leave();
}
static int __vipx_ioctl_get_unload_kernel_binary32(
struct vipx_ioc_unload_kernel_binary *karg,
struct vipx_ioc_unload_kernel_binary32 __user *uarg)
{
int ret;
vipx_enter();
if (get_user(karg->size, &uarg->size) ||
get_user(karg->global_id, &uarg->global_id) ||
get_user(karg->kernel_fd, &uarg->kernel_fd) ||
get_user(karg->kernel_size, &uarg->kernel_size)) {
ret = -EFAULT;
vipx_err("Copy failed [Unload Kernel Binary(32)]\n");
goto p_err;
}
memset(karg->timestamp, 0, sizeof(karg->timestamp));
memset(karg->reserved, 0, sizeof(karg->reserved));
vipx_leave();
return 0;
p_err:
return ret;
}
static void __vipx_ioctl_put_unload_kernel_binary32(
struct vipx_ioc_unload_kernel_binary *karg,
struct vipx_ioc_unload_kernel_binary32 __user *uarg)
{
vipx_enter();
if (put_user(karg->ret, &uarg->ret) ||
put_user(karg->timestamp[0].tv_sec,
&uarg->timestamp[0].tv_sec) ||
put_user(karg->timestamp[0].tv_nsec,
&uarg->timestamp[0].tv_nsec) ||
put_user(karg->timestamp[1].tv_sec,
&uarg->timestamp[1].tv_sec) ||
put_user(karg->timestamp[1].tv_nsec,
&uarg->timestamp[1].tv_nsec) ||
put_user(karg->timestamp[2].tv_sec,
&uarg->timestamp[2].tv_sec) ||
put_user(karg->timestamp[2].tv_nsec,
&uarg->timestamp[2].tv_nsec) ||
put_user(karg->timestamp[3].tv_sec,
&uarg->timestamp[3].tv_sec) ||
put_user(karg->timestamp[3].tv_nsec,
&uarg->timestamp[3].tv_nsec)) {
vipx_err("Copy failed to user [Unload kernel binary(32)]\n");
}
vipx_leave();
}
static int __vipx_ioctl_get_load_graph_info32(
struct vipx_ioc_load_graph_info *karg,
struct vipx_ioc_load_graph_info32 __user *uarg)
{
int ret;
vipx_enter();
if (get_user(karg->size, &uarg->size)) {
ret = -EFAULT;
vipx_err("Copy failed [Load graph info(32)]\n");
goto p_err;
}
ret = copy_from_user(&karg->graph_info, &uarg->graph_info,
sizeof(uarg->graph_info));
if (ret) {
vipx_err("Copy failed from user [Load graph info(32)]\n");
goto p_err;
}
memset(karg->timestamp, 0, sizeof(karg->timestamp));
memset(karg->reserved, 0, sizeof(karg->reserved));
vipx_leave();
return 0;
p_err:
return ret;
}
static void __vipx_ioctl_put_load_graph_info32(
struct vipx_ioc_load_graph_info *karg,
struct vipx_ioc_load_graph_info32 __user *uarg)
{
vipx_enter();
if (put_user(karg->ret, &uarg->ret) ||
put_user(karg->timestamp[0].tv_sec,
&uarg->timestamp[0].tv_sec) ||
put_user(karg->timestamp[0].tv_nsec,
&uarg->timestamp[0].tv_nsec) ||
put_user(karg->timestamp[1].tv_sec,
&uarg->timestamp[1].tv_sec) ||
put_user(karg->timestamp[1].tv_nsec,
&uarg->timestamp[1].tv_nsec) ||
put_user(karg->timestamp[2].tv_sec,
&uarg->timestamp[2].tv_sec) ||
put_user(karg->timestamp[2].tv_nsec,
&uarg->timestamp[2].tv_nsec) ||
put_user(karg->timestamp[3].tv_sec,
&uarg->timestamp[3].tv_sec) ||
put_user(karg->timestamp[3].tv_nsec,
&uarg->timestamp[3].tv_nsec)) {
vipx_err("Copy failed to user [Load kernel binary(32)]\n");
}
vipx_leave();
}
static int __vipx_ioctl_get_unload_graph_info32(
struct vipx_ioc_unload_graph_info *karg,
struct vipx_ioc_unload_graph_info32 __user *uarg)
{
int ret;
vipx_enter();
if (get_user(karg->size, &uarg->size) ||
get_user(karg->graph_id, &uarg->graph_id)) {
ret = -EFAULT;
vipx_err("Copy failed [Unload graph info(32)]\n");
goto p_err;
}
memset(karg->timestamp, 0, sizeof(karg->timestamp));
memset(karg->reserved, 0, sizeof(karg->reserved));
vipx_leave();
return 0;
p_err:
return ret;
}
static void __vipx_ioctl_put_unload_graph_info32(
struct vipx_ioc_unload_graph_info *karg,
struct vipx_ioc_unload_graph_info32 __user *uarg)
{
vipx_enter();
if (put_user(karg->ret, &uarg->ret) ||
put_user(karg->timestamp[0].tv_sec,
&uarg->timestamp[0].tv_sec) ||
put_user(karg->timestamp[0].tv_nsec,
&uarg->timestamp[0].tv_nsec) ||
put_user(karg->timestamp[1].tv_sec,
&uarg->timestamp[1].tv_sec) ||
put_user(karg->timestamp[1].tv_nsec,
&uarg->timestamp[1].tv_nsec) ||
put_user(karg->timestamp[2].tv_sec,
&uarg->timestamp[2].tv_sec) ||
put_user(karg->timestamp[2].tv_nsec,
&uarg->timestamp[2].tv_nsec) ||
put_user(karg->timestamp[3].tv_sec,
&uarg->timestamp[3].tv_sec) ||
put_user(karg->timestamp[3].tv_nsec,
&uarg->timestamp[3].tv_nsec)) {
vipx_err("Copy failed to user [Unload graph_info(32)]\n");
}
vipx_leave();
}
static int __vipx_ioctl_get_execute_submodel32(
struct vipx_ioc_execute_submodel *karg,
struct vipx_ioc_execute_submodel32 __user *uarg)
{
int ret;
vipx_enter();
if (get_user(karg->size, &uarg->size)) {
ret = -EFAULT;
vipx_err("Copy failed [Execute submodel(32)]\n");
goto p_err;
}
ret = copy_from_user(&karg->execute_info, &uarg->execute_info,
sizeof(uarg->execute_info));
if (ret) {
vipx_err("Copy failed from user [Execute submodel(32)]\n");
goto p_err;
}
memset(karg->timestamp, 0, sizeof(karg->timestamp));
memset(karg->reserved, 0, sizeof(karg->reserved));
vipx_leave();
return 0;
p_err:
return ret;
}
static void __vipx_ioctl_put_execute_submodel32(
struct vipx_ioc_execute_submodel *karg,
struct vipx_ioc_execute_submodel32 __user *uarg)
{
vipx_enter();
if (put_user(karg->ret, &uarg->ret) ||
put_user(karg->timestamp[0].tv_sec,
&uarg->timestamp[0].tv_sec) ||
put_user(karg->timestamp[0].tv_nsec,
&uarg->timestamp[0].tv_nsec) ||
put_user(karg->timestamp[1].tv_sec,
&uarg->timestamp[1].tv_sec) ||
put_user(karg->timestamp[1].tv_nsec,
&uarg->timestamp[1].tv_nsec) ||
put_user(karg->timestamp[2].tv_sec,
&uarg->timestamp[2].tv_sec) ||
put_user(karg->timestamp[2].tv_nsec,
&uarg->timestamp[2].tv_nsec) ||
put_user(karg->timestamp[3].tv_sec,
&uarg->timestamp[3].tv_sec) ||
put_user(karg->timestamp[3].tv_nsec,
&uarg->timestamp[3].tv_nsec)) {
vipx_err("Copy failed to user [Load kernel binary(32)]\n");
}
vipx_leave();
}
long vipx_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
struct vipx_context *vctx;
const struct vipx_ioctl_ops *ops;
union vipx_ioc_arg karg;
void __user *uarg;
vipx_enter();
vctx = file->private_data;
ops = vctx->core->ioc_ops;
uarg = compat_ptr(arg);
switch (cmd) {
case VIPX_IOC_LOAD_KERNEL_BINARY32:
ret = __vipx_ioctl_get_load_kernel_binary32(&karg.kernel_bin,
uarg);
if (ret)
goto p_err;
ret = ops->load_kernel_binary(vctx, &karg.kernel_bin);
__vipx_ioctl_put_load_kernel_binary32(&karg.kernel_bin, uarg);
break;
case VIPX_IOC_UNLOAD_KERNEL_BINARY32:
ret = __vipx_ioctl_get_unload_kernel_binary32(&karg.unload_kbin,
uarg);
if (ret)
goto p_err;
ret = ops->unload_kernel_binary(vctx, &karg.unload_kbin);
__vipx_ioctl_put_unload_kernel_binary32(&karg.unload_kbin,
uarg);
break;
case VIPX_IOC_LOAD_GRAPH_INFO32:
ret = __vipx_ioctl_get_load_graph_info32(&karg.load_ginfo,
uarg);
if (ret)
goto p_err;
ret = ops->load_graph_info(vctx, &karg.load_ginfo);
__vipx_ioctl_put_load_graph_info32(&karg.load_ginfo, uarg);
break;
case VIPX_IOC_UNLOAD_GRAPH_INFO32:
ret = __vipx_ioctl_get_unload_graph_info32(&karg.unload_ginfo,
uarg);
if (ret)
goto p_err;
ret = ops->unload_graph_info(vctx, &karg.unload_ginfo);
__vipx_ioctl_put_unload_graph_info32(&karg.unload_ginfo, uarg);
break;
case VIPX_IOC_EXECUTE_SUBMODEL32:
ret = __vipx_ioctl_get_execute_submodel32(&karg.exec, uarg);
if (ret)
goto p_err;
ret = ops->execute_submodel(vctx, &karg.exec);
__vipx_ioctl_put_execute_submodel32(&karg.exec, uarg);
break;
default:
ret = -EINVAL;
vipx_err("ioc command(%x) is not supported\n", cmd);
goto p_err;
}
vipx_leave();
p_err:
return ret;
}