]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/pci/intel/ipu-psys-compat32.c
UBUNTU: SAUCE: IPU driver release WW52
[mirror_ubuntu-jammy-kernel.git] / drivers / media / pci / intel / ipu-psys-compat32.c
CommitLineData
f2efa4ee
WY
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2013 - 2020 Intel Corporation
3
4#include <linux/compat.h>
5#include <linux/errno.h>
6#include <linux/uaccess.h>
7
8#include <uapi/linux/ipu-psys.h>
9
10#include "ipu-psys.h"
11
12static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
13{
14 long ret = -ENOTTY;
15
16 if (file->f_op->unlocked_ioctl)
17 ret = file->f_op->unlocked_ioctl(file, cmd, arg);
18
19 return ret;
20}
21
22struct ipu_psys_buffer32 {
23 u64 len;
24 union {
25 int fd;
26 compat_uptr_t userptr;
27 u64 reserved;
28 } base;
29 u32 data_offset;
30 u32 bytes_used;
31 u32 flags;
32 u32 reserved[2];
33} __packed;
34
35struct ipu_psys_command32 {
36 u64 issue_id;
37 u64 user_token;
38 u32 priority;
39 compat_uptr_t pg_manifest;
40 compat_uptr_t buffers;
41 int pg;
42 u32 pg_manifest_size;
43 u32 bufcount;
44 u32 min_psys_freq;
45 u32 frame_counter;
46 u32 reserved[2];
47} __packed;
48
49struct ipu_psys_manifest32 {
50 u32 index;
51 u32 size;
52 compat_uptr_t manifest;
53 u32 reserved[5];
54} __packed;
55
56static int
57get_ipu_psys_command32(struct ipu_psys_command *kp,
58 struct ipu_psys_command32 __user *up)
59{
60 compat_uptr_t pgm, bufs;
61 bool access_ok;
62
63 access_ok = access_ok(up, sizeof(struct ipu_psys_command32));
64 if (!access_ok || get_user(kp->issue_id, &up->issue_id) ||
65 get_user(kp->user_token, &up->user_token) ||
66 get_user(kp->priority, &up->priority) ||
67 get_user(pgm, &up->pg_manifest) ||
68 get_user(bufs, &up->buffers) ||
69 get_user(kp->pg, &up->pg) ||
70 get_user(kp->pg_manifest_size, &up->pg_manifest_size) ||
71 get_user(kp->bufcount, &up->bufcount) ||
72 get_user(kp->min_psys_freq, &up->min_psys_freq) ||
73 get_user(kp->frame_counter, &up->frame_counter)
74 )
75 return -EFAULT;
76
77 kp->pg_manifest = compat_ptr(pgm);
78 kp->buffers = compat_ptr(bufs);
79
80 return 0;
81}
82
83static int
84get_ipu_psys_buffer32(struct ipu_psys_buffer *kp,
85 struct ipu_psys_buffer32 __user *up)
86{
87 compat_uptr_t ptr;
88 bool access_ok;
89
90 access_ok = access_ok(up, sizeof(struct ipu_psys_buffer32));
91 if (!access_ok || get_user(kp->len, &up->len) ||
92 get_user(ptr, &up->base.userptr) ||
93 get_user(kp->data_offset, &up->data_offset) ||
94 get_user(kp->bytes_used, &up->bytes_used) ||
95 get_user(kp->flags, &up->flags))
96 return -EFAULT;
97
98 kp->base.userptr = compat_ptr(ptr);
99
100 return 0;
101}
102
103static int
104put_ipu_psys_buffer32(struct ipu_psys_buffer *kp,
105 struct ipu_psys_buffer32 __user *up)
106{
107 bool access_ok;
108
109 access_ok = access_ok(up, sizeof(struct ipu_psys_buffer32));
110 if (!access_ok || put_user(kp->len, &up->len) ||
111 put_user(kp->base.fd, &up->base.fd) ||
112 put_user(kp->data_offset, &up->data_offset) ||
113 put_user(kp->bytes_used, &up->bytes_used) ||
114 put_user(kp->flags, &up->flags))
115 return -EFAULT;
116
117 return 0;
118}
119
120static int
121get_ipu_psys_manifest32(struct ipu_psys_manifest *kp,
122 struct ipu_psys_manifest32 __user *up)
123{
124 compat_uptr_t ptr;
125 bool access_ok;
126
127 access_ok = access_ok(up, sizeof(struct ipu_psys_manifest32));
128 if (!access_ok || get_user(kp->index, &up->index) ||
129 get_user(kp->size, &up->size) || get_user(ptr, &up->manifest))
130 return -EFAULT;
131
132 kp->manifest = compat_ptr(ptr);
133
134 return 0;
135}
136
137static int
138put_ipu_psys_manifest32(struct ipu_psys_manifest *kp,
139 struct ipu_psys_manifest32 __user *up)
140{
141 compat_uptr_t ptr = (u32)((unsigned long)kp->manifest);
142 bool access_ok;
143
144 access_ok = access_ok(up, sizeof(struct ipu_psys_manifest32));
145 if (!access_ok || put_user(kp->index, &up->index) ||
146 put_user(kp->size, &up->size) || put_user(ptr, &up->manifest))
147 return -EFAULT;
148
149 return 0;
150}
151
152#define IPU_IOC_GETBUF32 _IOWR('A', 4, struct ipu_psys_buffer32)
153#define IPU_IOC_PUTBUF32 _IOWR('A', 5, struct ipu_psys_buffer32)
154#define IPU_IOC_QCMD32 _IOWR('A', 6, struct ipu_psys_command32)
155#define IPU_IOC_CMD_CANCEL32 _IOWR('A', 8, struct ipu_psys_command32)
156#define IPU_IOC_GET_MANIFEST32 _IOWR('A', 9, struct ipu_psys_manifest32)
157
158long ipu_psys_compat_ioctl32(struct file *file, unsigned int cmd,
159 unsigned long arg)
160{
161 union {
162 struct ipu_psys_buffer buf;
163 struct ipu_psys_command cmd;
164 struct ipu_psys_event ev;
165 struct ipu_psys_manifest m;
166 } karg;
167 int compatible_arg = 1;
168 int err = 0;
169 void __user *up = compat_ptr(arg);
170
171 switch (cmd) {
172 case IPU_IOC_GETBUF32:
173 cmd = IPU_IOC_GETBUF;
174 break;
175 case IPU_IOC_PUTBUF32:
176 cmd = IPU_IOC_PUTBUF;
177 break;
178 case IPU_IOC_QCMD32:
179 cmd = IPU_IOC_QCMD;
180 break;
181 case IPU_IOC_GET_MANIFEST32:
182 cmd = IPU_IOC_GET_MANIFEST;
183 break;
184 }
185
186 switch (cmd) {
187 case IPU_IOC_GETBUF:
188 case IPU_IOC_PUTBUF:
189 err = get_ipu_psys_buffer32(&karg.buf, up);
190 compatible_arg = 0;
191 break;
192 case IPU_IOC_QCMD:
193 err = get_ipu_psys_command32(&karg.cmd, up);
194 compatible_arg = 0;
195 break;
196 case IPU_IOC_GET_MANIFEST:
197 err = get_ipu_psys_manifest32(&karg.m, up);
198 compatible_arg = 0;
199 break;
200 }
201 if (err)
202 return err;
203
204 if (compatible_arg) {
205 err = native_ioctl(file, cmd, (unsigned long)up);
206 } else {
3ebd4441 207 mm_segment_t old_fs = force_uaccess_begin();
f2efa4ee 208
f2efa4ee 209 err = native_ioctl(file, cmd, (unsigned long)&karg);
3ebd4441 210 force_uaccess_end(old_fs);
f2efa4ee
WY
211 }
212
213 if (err)
214 return err;
215
216 switch (cmd) {
217 case IPU_IOC_GETBUF:
218 err = put_ipu_psys_buffer32(&karg.buf, up);
219 break;
220 case IPU_IOC_GET_MANIFEST:
221 err = put_ipu_psys_manifest32(&karg.m, up);
222 break;
223 }
224 return err;
225}
226EXPORT_SYMBOL_GPL(ipu_psys_compat_ioctl32);