clear-pkgs-linux-iot-lts2018/0811-media-intel-ipu4-VIRT-...

304 lines
8.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ong Hock Yu <ong.hock.yu@intel.com>
Date: Fri, 12 Oct 2018 02:48:00 +0800
Subject: [PATCH] media: intel-ipu4: [VIRT] Add 32 bits IOTCL support for IPU
PSYS virtualization.
Change-Id: Ib6fbbe326e2e892011134f04a341c47000a86434
Tracked-On: OAM-64123
Tracked-On: OAM-64294
Tracked-On: OAM-64937
Tracked-On: OLINUX-2973
Tracked-On: OLINUX-3042
Signed-off-by: Ong Hock Yu <ong.hock.yu@intel.com>
---
drivers/media/pci/intel/virtio/Makefile.virt | 3 +
.../intel/virtio/intel-ipu4-para-virt-psys.c | 16 +-
.../intel-ipu4-virtio-fe-psys-32compat.c | 225 ++++++++++++++++++
3 files changed, 234 insertions(+), 10 deletions(-)
create mode 100644 drivers/media/pci/intel/virtio/intel-ipu4-virtio-fe-psys-32compat.c
diff --git a/drivers/media/pci/intel/virtio/Makefile.virt b/drivers/media/pci/intel/virtio/Makefile.virt
index 232027011136..df41ac23a501 100644
--- a/drivers/media/pci/intel/virtio/Makefile.virt
+++ b/drivers/media/pci/intel/virtio/Makefile.virt
@@ -20,6 +20,9 @@ else
$(TARGET_MODULE)-objs += ../virtio/intel-ipu4-virtio-fe.o
$(TARGET_MODULE)-objs += ../virtio/intel-ipu4-para-virt-drv.o
$(TARGET_MODULE)-objs += ../virtio/intel-ipu4-para-virt-psys.o
+ifdef CONFIG_COMPAT
+ $(TARGET_MODULE)-objs += ../virtio/intel-ipu4-virtio-fe-psys-32compat.o
+endif
endif
obj-$(CONFIG_VIDEO_INTEL_IPU_ACRN) += $(TARGET_MODULE).o
\ No newline at end of file
diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c
index 7751f471af1d..f2f57b086739 100644
--- a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c
+++ b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c
@@ -37,6 +37,12 @@
#define IPU_PSYS_NUM_DEVICES 4
#define IPU_PSYS_NAME "intel-ipu4-psys"
+
+#ifdef CONFIG_COMPAT
+extern long virt_psys_compat_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg);
+#endif
+
static dev_t virt_psys_dev_t;
static struct virt_ipu_psys *g_psys;
@@ -466,16 +472,6 @@ long ipu_ioctl_dqevent(struct ipu_psys_event *event,
return rval;
}
-long virt_psys_compat_ioctl32(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int err = 0;
-
- if (err)
- return err;
-
- return 0;
-}
static long virt_psys_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-virtio-fe-psys-32compat.c b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-fe-psys-32compat.c
new file mode 100644
index 000000000000..6756dd333cf8
--- /dev/null
+++ b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-fe-psys-32compat.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2013 - 2018 Intel Corporation
+
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+
+#include <uapi/linux/ipu-psys.h>
+
+#include "ipu-psys.h"
+
+static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret = -ENOTTY;
+
+ if (file->f_op->unlocked_ioctl)
+ ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+
+ return ret;
+}
+
+struct ipu_psys_buffer32 {
+ u64 len;
+ union {
+ int fd;
+ compat_uptr_t userptr;
+ u64 reserved;
+ } base;
+ u32 data_offset;
+ u32 bytes_used;
+ u32 flags;
+ u32 reserved[2];
+} __packed;
+
+struct ipu_psys_command32 {
+ u64 issue_id;
+ u64 user_token;
+ u32 priority;
+ compat_uptr_t pg_manifest;
+ compat_uptr_t buffers;
+ int pg;
+ u32 pg_manifest_size;
+ u32 bufcount;
+ u32 min_psys_freq;
+ u32 frame_counter;
+ u32 reserved[2];
+} __packed;
+
+struct ipu_psys_manifest32 {
+ u32 index;
+ u32 size;
+ compat_uptr_t manifest;
+ u32 reserved[5];
+} __packed;
+
+static int
+get_ipu_psys_command32(struct ipu_psys_command *kp,
+ struct ipu_psys_command32 __user *up)
+{
+ compat_uptr_t pgm, bufs;
+
+ if (!access_ok(VERIFY_READ, up,
+ sizeof(struct ipu_psys_command32)) ||
+ get_user(kp->issue_id, &up->issue_id) ||
+ get_user(kp->user_token, &up->user_token) ||
+ get_user(kp->priority, &up->priority) ||
+ get_user(pgm, &up->pg_manifest) ||
+ get_user(bufs, &up->buffers) ||
+ get_user(kp->pg, &up->pg) ||
+ get_user(kp->pg_manifest_size, &up->pg_manifest_size) ||
+ get_user(kp->bufcount, &up->bufcount) ||
+ get_user(kp->min_psys_freq, &up->min_psys_freq)
+ || get_user(kp->frame_counter, &up->frame_counter)
+ )
+ return -EFAULT;
+
+ kp->pg_manifest = compat_ptr(pgm);
+ kp->buffers = compat_ptr(bufs);
+
+ return 0;
+}
+
+static int
+get_ipu_psys_buffer32(struct ipu_psys_buffer *kp,
+ struct ipu_psys_buffer32 __user *up)
+{
+ compat_uptr_t ptr;
+
+ if (!access_ok(VERIFY_READ, up,
+ sizeof(struct ipu_psys_buffer32)) ||
+ get_user(kp->len, &up->len) ||
+ get_user(ptr, &up->base.userptr) ||
+ get_user(kp->data_offset, &up->data_offset) ||
+ get_user(kp->bytes_used, &up->bytes_used) ||
+ get_user(kp->flags, &up->flags))
+ return -EFAULT;
+
+ kp->base.userptr = compat_ptr(ptr);
+
+ return 0;
+}
+
+static int
+put_ipu_psys_buffer32(struct ipu_psys_buffer *kp,
+ struct ipu_psys_buffer32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up,
+ sizeof(struct ipu_psys_buffer32)) ||
+ put_user(kp->len, &up->len) ||
+ put_user(kp->base.fd, &up->base.fd) ||
+ put_user(kp->data_offset, &up->data_offset) ||
+ put_user(kp->bytes_used, &up->bytes_used) ||
+ put_user(kp->flags, &up->flags))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int
+get_ipu_psys_manifest32(struct ipu_psys_manifest *kp,
+ struct ipu_psys_manifest32 __user *up)
+{
+ compat_uptr_t ptr;
+
+ if (!access_ok(VERIFY_READ, up,
+ sizeof(struct ipu_psys_manifest32)) ||
+ get_user(kp->index, &up->index) ||
+ get_user(kp->size, &up->size) || get_user(ptr, &up->manifest))
+ return -EFAULT;
+
+ kp->manifest = compat_ptr(ptr);
+
+ return 0;
+}
+
+static int
+put_ipu_psys_manifest32(struct ipu_psys_manifest *kp,
+ struct ipu_psys_manifest32 __user *up)
+{
+ compat_uptr_t ptr = (u32)((unsigned long)kp->manifest);
+
+ if (!access_ok(VERIFY_WRITE, up,
+ sizeof(struct ipu_psys_manifest32)) ||
+ put_user(kp->index, &up->index) ||
+ put_user(kp->size, &up->size) || put_user(ptr, &up->manifest))
+ return -EFAULT;
+
+ return 0;
+}
+
+#define IPU_IOC_GETBUF32 _IOWR('A', 4, struct ipu_psys_buffer32)
+#define IPU_IOC_PUTBUF32 _IOWR('A', 5, struct ipu_psys_buffer32)
+#define IPU_IOC_QCMD32 _IOWR('A', 6, struct ipu_psys_command32)
+#define IPU_IOC_CMD_CANCEL32 _IOWR('A', 8, struct ipu_psys_command32)
+#define IPU_IOC_GET_MANIFEST32 _IOWR('A', 9, struct ipu_psys_manifest32)
+
+long virt_psys_compat_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ union {
+ struct ipu_psys_buffer buf;
+ struct ipu_psys_command cmd;
+ struct ipu_psys_event ev;
+ struct ipu_psys_manifest m;
+ } karg;
+ int compatible_arg = 1;
+ int err = 0;
+ void __user *up = compat_ptr(arg);
+
+ switch (cmd) {
+ case IPU_IOC_GETBUF32:
+ cmd = IPU_IOC_GETBUF;
+ break;
+ case IPU_IOC_PUTBUF32:
+ cmd = IPU_IOC_PUTBUF;
+ break;
+ case IPU_IOC_QCMD32:
+ cmd = IPU_IOC_QCMD;
+ break;
+ case IPU_IOC_GET_MANIFEST32:
+ cmd = IPU_IOC_GET_MANIFEST;
+ break;
+ }
+
+ switch (cmd) {
+ case IPU_IOC_GETBUF:
+ case IPU_IOC_PUTBUF:
+ err = get_ipu_psys_buffer32(&karg.buf, up);
+ compatible_arg = 0;
+ break;
+ case IPU_IOC_QCMD:
+ err = get_ipu_psys_command32(&karg.cmd, up);
+ compatible_arg = 0;
+ break;
+ case IPU_IOC_GET_MANIFEST:
+ err = get_ipu_psys_manifest32(&karg.m, up);
+ compatible_arg = 0;
+ break;
+ }
+ if (err)
+ return err;
+
+ if (compatible_arg) {
+ err = native_ioctl(file, cmd, (unsigned long)up);
+ } else {
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ err = native_ioctl(file, cmd, (unsigned long)&karg);
+ set_fs(old_fs);
+ }
+
+ if (err)
+ return err;
+
+ switch (cmd) {
+ case IPU_IOC_GETBUF:
+ err = put_ipu_psys_buffer32(&karg.buf, up);
+ break;
+ case IPU_IOC_GET_MANIFEST:
+ err = put_ipu_psys_manifest32(&karg.m, up);
+ break;
+ }
+ return err;
+}
--
https://clearlinux.org