304 lines
8.0 KiB
Diff
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
|
|
|