1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * \file drm_ioc32.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * 32-bit ioctl compatibility routines for the DRM.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * \author Paul Mackerras <paulus@samba.org>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (C) Paul Mackerras 2005.
9*4882a593Smuzhiyun * All Rights Reserved.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
12*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
13*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
14*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
16*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
19*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
20*4882a593Smuzhiyun * Software.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25*4882a593Smuzhiyun * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27*4882a593Smuzhiyun * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28*4882a593Smuzhiyun * IN THE SOFTWARE.
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun #include <linux/compat.h>
31*4882a593Smuzhiyun #include <linux/ratelimit.h>
32*4882a593Smuzhiyun #include <linux/export.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <drm/drm_agpsupport.h>
35*4882a593Smuzhiyun #include <drm/drm_file.h>
36*4882a593Smuzhiyun #include <drm/drm_print.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include "drm_crtc_internal.h"
39*4882a593Smuzhiyun #include "drm_internal.h"
40*4882a593Smuzhiyun #include "drm_legacy.h"
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
43*4882a593Smuzhiyun #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
44*4882a593Smuzhiyun #define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
45*4882a593Smuzhiyun #define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t)
46*4882a593Smuzhiyun #define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t)
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t)
49*4882a593Smuzhiyun #define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t)
50*4882a593Smuzhiyun #define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t)
51*4882a593Smuzhiyun #define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t)
52*4882a593Smuzhiyun #define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t)
53*4882a593Smuzhiyun #define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t)
54*4882a593Smuzhiyun #define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t)
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
59*4882a593Smuzhiyun #define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t)
62*4882a593Smuzhiyun #define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t)
65*4882a593Smuzhiyun #define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t)
66*4882a593Smuzhiyun #define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t)
67*4882a593Smuzhiyun #define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t)
68*4882a593Smuzhiyun #define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t)
69*4882a593Smuzhiyun #define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t)
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
72*4882a593Smuzhiyun #define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define DRM_IOCTL_UPDATE_DRAW32 DRM_IOW( 0x3f, drm_update_draw32_t)
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #define DRM_IOCTL_MODE_ADDFB232 DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun typedef struct drm_version_32 {
81*4882a593Smuzhiyun int version_major; /* Major version */
82*4882a593Smuzhiyun int version_minor; /* Minor version */
83*4882a593Smuzhiyun int version_patchlevel; /* Patch level */
84*4882a593Smuzhiyun u32 name_len; /* Length of name buffer */
85*4882a593Smuzhiyun u32 name; /* Name of driver */
86*4882a593Smuzhiyun u32 date_len; /* Length of date buffer */
87*4882a593Smuzhiyun u32 date; /* User-space buffer to hold date */
88*4882a593Smuzhiyun u32 desc_len; /* Length of desc buffer */
89*4882a593Smuzhiyun u32 desc; /* User-space buffer to hold desc */
90*4882a593Smuzhiyun } drm_version32_t;
91*4882a593Smuzhiyun
compat_drm_version(struct file * file,unsigned int cmd,unsigned long arg)92*4882a593Smuzhiyun static int compat_drm_version(struct file *file, unsigned int cmd,
93*4882a593Smuzhiyun unsigned long arg)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun drm_version32_t v32;
96*4882a593Smuzhiyun struct drm_version v;
97*4882a593Smuzhiyun int err;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
100*4882a593Smuzhiyun return -EFAULT;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun memset(&v, 0, sizeof(v));
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun v = (struct drm_version) {
105*4882a593Smuzhiyun .name_len = v32.name_len,
106*4882a593Smuzhiyun .name = compat_ptr(v32.name),
107*4882a593Smuzhiyun .date_len = v32.date_len,
108*4882a593Smuzhiyun .date = compat_ptr(v32.date),
109*4882a593Smuzhiyun .desc_len = v32.desc_len,
110*4882a593Smuzhiyun .desc = compat_ptr(v32.desc),
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_version, &v,
113*4882a593Smuzhiyun DRM_RENDER_ALLOW);
114*4882a593Smuzhiyun if (err)
115*4882a593Smuzhiyun return err;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun v32.version_major = v.version_major;
118*4882a593Smuzhiyun v32.version_minor = v.version_minor;
119*4882a593Smuzhiyun v32.version_patchlevel = v.version_patchlevel;
120*4882a593Smuzhiyun v32.name_len = v.name_len;
121*4882a593Smuzhiyun v32.date_len = v.date_len;
122*4882a593Smuzhiyun v32.desc_len = v.desc_len;
123*4882a593Smuzhiyun if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
124*4882a593Smuzhiyun return -EFAULT;
125*4882a593Smuzhiyun return 0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun typedef struct drm_unique32 {
129*4882a593Smuzhiyun u32 unique_len; /* Length of unique */
130*4882a593Smuzhiyun u32 unique; /* Unique name for driver instantiation */
131*4882a593Smuzhiyun } drm_unique32_t;
132*4882a593Smuzhiyun
compat_drm_getunique(struct file * file,unsigned int cmd,unsigned long arg)133*4882a593Smuzhiyun static int compat_drm_getunique(struct file *file, unsigned int cmd,
134*4882a593Smuzhiyun unsigned long arg)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun drm_unique32_t uq32;
137*4882a593Smuzhiyun struct drm_unique uq;
138*4882a593Smuzhiyun int err;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
141*4882a593Smuzhiyun return -EFAULT;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun memset(&uq, 0, sizeof(uq));
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun uq = (struct drm_unique){
146*4882a593Smuzhiyun .unique_len = uq32.unique_len,
147*4882a593Smuzhiyun .unique = compat_ptr(uq32.unique),
148*4882a593Smuzhiyun };
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_getunique, &uq, 0);
151*4882a593Smuzhiyun if (err)
152*4882a593Smuzhiyun return err;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun uq32.unique_len = uq.unique_len;
155*4882a593Smuzhiyun if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
156*4882a593Smuzhiyun return -EFAULT;
157*4882a593Smuzhiyun return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
compat_drm_setunique(struct file * file,unsigned int cmd,unsigned long arg)160*4882a593Smuzhiyun static int compat_drm_setunique(struct file *file, unsigned int cmd,
161*4882a593Smuzhiyun unsigned long arg)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun /* it's dead */
164*4882a593Smuzhiyun return -EINVAL;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
168*4882a593Smuzhiyun typedef struct drm_map32 {
169*4882a593Smuzhiyun u32 offset; /* Requested physical address (0 for SAREA) */
170*4882a593Smuzhiyun u32 size; /* Requested physical size (bytes) */
171*4882a593Smuzhiyun enum drm_map_type type; /* Type of memory to map */
172*4882a593Smuzhiyun enum drm_map_flags flags; /* Flags */
173*4882a593Smuzhiyun u32 handle; /* User-space: "Handle" to pass to mmap() */
174*4882a593Smuzhiyun int mtrr; /* MTRR slot used */
175*4882a593Smuzhiyun } drm_map32_t;
176*4882a593Smuzhiyun
compat_drm_getmap(struct file * file,unsigned int cmd,unsigned long arg)177*4882a593Smuzhiyun static int compat_drm_getmap(struct file *file, unsigned int cmd,
178*4882a593Smuzhiyun unsigned long arg)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun drm_map32_t __user *argp = (void __user *)arg;
181*4882a593Smuzhiyun drm_map32_t m32;
182*4882a593Smuzhiyun struct drm_map map;
183*4882a593Smuzhiyun int err;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (copy_from_user(&m32, argp, sizeof(m32)))
186*4882a593Smuzhiyun return -EFAULT;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun map.offset = m32.offset;
189*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0);
190*4882a593Smuzhiyun if (err)
191*4882a593Smuzhiyun return err;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun m32.offset = map.offset;
194*4882a593Smuzhiyun m32.size = map.size;
195*4882a593Smuzhiyun m32.type = map.type;
196*4882a593Smuzhiyun m32.flags = map.flags;
197*4882a593Smuzhiyun m32.handle = ptr_to_compat((void __user *)map.handle);
198*4882a593Smuzhiyun m32.mtrr = map.mtrr;
199*4882a593Smuzhiyun if (copy_to_user(argp, &m32, sizeof(m32)))
200*4882a593Smuzhiyun return -EFAULT;
201*4882a593Smuzhiyun return 0;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
compat_drm_addmap(struct file * file,unsigned int cmd,unsigned long arg)205*4882a593Smuzhiyun static int compat_drm_addmap(struct file *file, unsigned int cmd,
206*4882a593Smuzhiyun unsigned long arg)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun drm_map32_t __user *argp = (void __user *)arg;
209*4882a593Smuzhiyun drm_map32_t m32;
210*4882a593Smuzhiyun struct drm_map map;
211*4882a593Smuzhiyun int err;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (copy_from_user(&m32, argp, sizeof(m32)))
214*4882a593Smuzhiyun return -EFAULT;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun map.offset = m32.offset;
217*4882a593Smuzhiyun map.size = m32.size;
218*4882a593Smuzhiyun map.type = m32.type;
219*4882a593Smuzhiyun map.flags = m32.flags;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map,
222*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
223*4882a593Smuzhiyun if (err)
224*4882a593Smuzhiyun return err;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun m32.offset = map.offset;
227*4882a593Smuzhiyun m32.mtrr = map.mtrr;
228*4882a593Smuzhiyun m32.handle = ptr_to_compat((void __user *)map.handle);
229*4882a593Smuzhiyun if (map.handle != compat_ptr(m32.handle))
230*4882a593Smuzhiyun pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n",
231*4882a593Smuzhiyun map.handle, m32.type, m32.offset);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if (copy_to_user(argp, &m32, sizeof(m32)))
234*4882a593Smuzhiyun return -EFAULT;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun return 0;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
compat_drm_rmmap(struct file * file,unsigned int cmd,unsigned long arg)239*4882a593Smuzhiyun static int compat_drm_rmmap(struct file *file, unsigned int cmd,
240*4882a593Smuzhiyun unsigned long arg)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun drm_map32_t __user *argp = (void __user *)arg;
243*4882a593Smuzhiyun struct drm_map map;
244*4882a593Smuzhiyun u32 handle;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (get_user(handle, &argp->handle))
247*4882a593Smuzhiyun return -EFAULT;
248*4882a593Smuzhiyun map.handle = compat_ptr(handle);
249*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun #endif
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun typedef struct drm_client32 {
254*4882a593Smuzhiyun int idx; /* Which client desired? */
255*4882a593Smuzhiyun int auth; /* Is client authenticated? */
256*4882a593Smuzhiyun u32 pid; /* Process ID */
257*4882a593Smuzhiyun u32 uid; /* User ID */
258*4882a593Smuzhiyun u32 magic; /* Magic */
259*4882a593Smuzhiyun u32 iocs; /* Ioctl count */
260*4882a593Smuzhiyun } drm_client32_t;
261*4882a593Smuzhiyun
compat_drm_getclient(struct file * file,unsigned int cmd,unsigned long arg)262*4882a593Smuzhiyun static int compat_drm_getclient(struct file *file, unsigned int cmd,
263*4882a593Smuzhiyun unsigned long arg)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun drm_client32_t c32;
266*4882a593Smuzhiyun drm_client32_t __user *argp = (void __user *)arg;
267*4882a593Smuzhiyun struct drm_client client;
268*4882a593Smuzhiyun int err;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun if (copy_from_user(&c32, argp, sizeof(c32)))
271*4882a593Smuzhiyun return -EFAULT;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun memset(&client, 0, sizeof(client));
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun client.idx = c32.idx;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
278*4882a593Smuzhiyun if (err)
279*4882a593Smuzhiyun return err;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun c32.idx = client.idx;
282*4882a593Smuzhiyun c32.auth = client.auth;
283*4882a593Smuzhiyun c32.pid = client.pid;
284*4882a593Smuzhiyun c32.uid = client.uid;
285*4882a593Smuzhiyun c32.magic = client.magic;
286*4882a593Smuzhiyun c32.iocs = client.iocs;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun if (copy_to_user(argp, &c32, sizeof(c32)))
289*4882a593Smuzhiyun return -EFAULT;
290*4882a593Smuzhiyun return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun typedef struct drm_stats32 {
294*4882a593Smuzhiyun u32 count;
295*4882a593Smuzhiyun struct {
296*4882a593Smuzhiyun u32 value;
297*4882a593Smuzhiyun enum drm_stat_type type;
298*4882a593Smuzhiyun } data[15];
299*4882a593Smuzhiyun } drm_stats32_t;
300*4882a593Smuzhiyun
compat_drm_getstats(struct file * file,unsigned int cmd,unsigned long arg)301*4882a593Smuzhiyun static int compat_drm_getstats(struct file *file, unsigned int cmd,
302*4882a593Smuzhiyun unsigned long arg)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun drm_stats32_t __user *argp = (void __user *)arg;
305*4882a593Smuzhiyun int err;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_noop, NULL, 0);
308*4882a593Smuzhiyun if (err)
309*4882a593Smuzhiyun return err;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun if (clear_user(argp, sizeof(drm_stats32_t)))
312*4882a593Smuzhiyun return -EFAULT;
313*4882a593Smuzhiyun return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
317*4882a593Smuzhiyun typedef struct drm_buf_desc32 {
318*4882a593Smuzhiyun int count; /* Number of buffers of this size */
319*4882a593Smuzhiyun int size; /* Size in bytes */
320*4882a593Smuzhiyun int low_mark; /* Low water mark */
321*4882a593Smuzhiyun int high_mark; /* High water mark */
322*4882a593Smuzhiyun int flags;
323*4882a593Smuzhiyun u32 agp_start; /* Start address in the AGP aperture */
324*4882a593Smuzhiyun } drm_buf_desc32_t;
325*4882a593Smuzhiyun
compat_drm_addbufs(struct file * file,unsigned int cmd,unsigned long arg)326*4882a593Smuzhiyun static int compat_drm_addbufs(struct file *file, unsigned int cmd,
327*4882a593Smuzhiyun unsigned long arg)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun drm_buf_desc32_t __user *argp = (void __user *)arg;
330*4882a593Smuzhiyun drm_buf_desc32_t desc32;
331*4882a593Smuzhiyun struct drm_buf_desc desc;
332*4882a593Smuzhiyun int err;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t)))
335*4882a593Smuzhiyun return -EFAULT;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun desc = (struct drm_buf_desc){
338*4882a593Smuzhiyun desc32.count, desc32.size, desc32.low_mark, desc32.high_mark,
339*4882a593Smuzhiyun desc32.flags, desc32.agp_start
340*4882a593Smuzhiyun };
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc,
343*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
344*4882a593Smuzhiyun if (err)
345*4882a593Smuzhiyun return err;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun desc32 = (drm_buf_desc32_t){
348*4882a593Smuzhiyun desc.count, desc.size, desc.low_mark, desc.high_mark,
349*4882a593Smuzhiyun desc.flags, desc.agp_start
350*4882a593Smuzhiyun };
351*4882a593Smuzhiyun if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t)))
352*4882a593Smuzhiyun return -EFAULT;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
compat_drm_markbufs(struct file * file,unsigned int cmd,unsigned long arg)357*4882a593Smuzhiyun static int compat_drm_markbufs(struct file *file, unsigned int cmd,
358*4882a593Smuzhiyun unsigned long arg)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun drm_buf_desc32_t b32;
361*4882a593Smuzhiyun drm_buf_desc32_t __user *argp = (void __user *)arg;
362*4882a593Smuzhiyun struct drm_buf_desc buf;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun if (copy_from_user(&b32, argp, sizeof(b32)))
365*4882a593Smuzhiyun return -EFAULT;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun buf.size = b32.size;
368*4882a593Smuzhiyun buf.low_mark = b32.low_mark;
369*4882a593Smuzhiyun buf.high_mark = b32.high_mark;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf,
372*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun typedef struct drm_buf_info32 {
376*4882a593Smuzhiyun int count; /**< Entries in list */
377*4882a593Smuzhiyun u32 list;
378*4882a593Smuzhiyun } drm_buf_info32_t;
379*4882a593Smuzhiyun
copy_one_buf32(void * data,int count,struct drm_buf_entry * from)380*4882a593Smuzhiyun static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun drm_buf_info32_t *request = data;
383*4882a593Smuzhiyun drm_buf_desc32_t __user *to = compat_ptr(request->list);
384*4882a593Smuzhiyun drm_buf_desc32_t v = {.count = from->buf_count,
385*4882a593Smuzhiyun .size = from->buf_size,
386*4882a593Smuzhiyun .low_mark = from->low_mark,
387*4882a593Smuzhiyun .high_mark = from->high_mark};
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)))
390*4882a593Smuzhiyun return -EFAULT;
391*4882a593Smuzhiyun return 0;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
drm_legacy_infobufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)394*4882a593Smuzhiyun static int drm_legacy_infobufs32(struct drm_device *dev, void *data,
395*4882a593Smuzhiyun struct drm_file *file_priv)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun drm_buf_info32_t *request = data;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
compat_drm_infobufs(struct file * file,unsigned int cmd,unsigned long arg)402*4882a593Smuzhiyun static int compat_drm_infobufs(struct file *file, unsigned int cmd,
403*4882a593Smuzhiyun unsigned long arg)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun drm_buf_info32_t req32;
406*4882a593Smuzhiyun drm_buf_info32_t __user *argp = (void __user *)arg;
407*4882a593Smuzhiyun int err;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
410*4882a593Smuzhiyun return -EFAULT;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if (req32.count < 0)
413*4882a593Smuzhiyun req32.count = 0;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH);
416*4882a593Smuzhiyun if (err)
417*4882a593Smuzhiyun return err;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (put_user(req32.count, &argp->count))
420*4882a593Smuzhiyun return -EFAULT;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun return 0;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun typedef struct drm_buf_pub32 {
426*4882a593Smuzhiyun int idx; /**< Index into the master buffer list */
427*4882a593Smuzhiyun int total; /**< Buffer size */
428*4882a593Smuzhiyun int used; /**< Amount of buffer in use (for DMA) */
429*4882a593Smuzhiyun u32 address; /**< Address of buffer */
430*4882a593Smuzhiyun } drm_buf_pub32_t;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun typedef struct drm_buf_map32 {
433*4882a593Smuzhiyun int count; /**< Length of the buffer list */
434*4882a593Smuzhiyun u32 virtual; /**< Mmap'd area in user-virtual */
435*4882a593Smuzhiyun u32 list; /**< Buffer information */
436*4882a593Smuzhiyun } drm_buf_map32_t;
437*4882a593Smuzhiyun
map_one_buf32(void * data,int idx,unsigned long virtual,struct drm_buf * buf)438*4882a593Smuzhiyun static int map_one_buf32(void *data, int idx, unsigned long virtual,
439*4882a593Smuzhiyun struct drm_buf *buf)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun drm_buf_map32_t *request = data;
442*4882a593Smuzhiyun drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx;
443*4882a593Smuzhiyun drm_buf_pub32_t v;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun v.idx = buf->idx;
446*4882a593Smuzhiyun v.total = buf->total;
447*4882a593Smuzhiyun v.used = 0;
448*4882a593Smuzhiyun v.address = virtual + buf->offset;
449*4882a593Smuzhiyun if (copy_to_user(to, &v, sizeof(v)))
450*4882a593Smuzhiyun return -EFAULT;
451*4882a593Smuzhiyun return 0;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
drm_legacy_mapbufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)454*4882a593Smuzhiyun static int drm_legacy_mapbufs32(struct drm_device *dev, void *data,
455*4882a593Smuzhiyun struct drm_file *file_priv)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun drm_buf_map32_t *request = data;
458*4882a593Smuzhiyun void __user *v;
459*4882a593Smuzhiyun int err = __drm_legacy_mapbufs(dev, data, &request->count,
460*4882a593Smuzhiyun &v, map_one_buf32,
461*4882a593Smuzhiyun file_priv);
462*4882a593Smuzhiyun request->virtual = ptr_to_compat(v);
463*4882a593Smuzhiyun return err;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
compat_drm_mapbufs(struct file * file,unsigned int cmd,unsigned long arg)466*4882a593Smuzhiyun static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
467*4882a593Smuzhiyun unsigned long arg)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun drm_buf_map32_t __user *argp = (void __user *)arg;
470*4882a593Smuzhiyun drm_buf_map32_t req32;
471*4882a593Smuzhiyun int err;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
474*4882a593Smuzhiyun return -EFAULT;
475*4882a593Smuzhiyun if (req32.count < 0)
476*4882a593Smuzhiyun return -EINVAL;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH);
479*4882a593Smuzhiyun if (err)
480*4882a593Smuzhiyun return err;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (put_user(req32.count, &argp->count)
483*4882a593Smuzhiyun || put_user(req32.virtual, &argp->virtual))
484*4882a593Smuzhiyun return -EFAULT;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun return 0;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun typedef struct drm_buf_free32 {
490*4882a593Smuzhiyun int count;
491*4882a593Smuzhiyun u32 list;
492*4882a593Smuzhiyun } drm_buf_free32_t;
493*4882a593Smuzhiyun
compat_drm_freebufs(struct file * file,unsigned int cmd,unsigned long arg)494*4882a593Smuzhiyun static int compat_drm_freebufs(struct file *file, unsigned int cmd,
495*4882a593Smuzhiyun unsigned long arg)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun drm_buf_free32_t req32;
498*4882a593Smuzhiyun struct drm_buf_free request;
499*4882a593Smuzhiyun drm_buf_free32_t __user *argp = (void __user *)arg;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
502*4882a593Smuzhiyun return -EFAULT;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun request.count = req32.count;
505*4882a593Smuzhiyun request.list = compat_ptr(req32.list);
506*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun typedef struct drm_ctx_priv_map32 {
510*4882a593Smuzhiyun unsigned int ctx_id; /**< Context requesting private mapping */
511*4882a593Smuzhiyun u32 handle; /**< Handle of map */
512*4882a593Smuzhiyun } drm_ctx_priv_map32_t;
513*4882a593Smuzhiyun
compat_drm_setsareactx(struct file * file,unsigned int cmd,unsigned long arg)514*4882a593Smuzhiyun static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
515*4882a593Smuzhiyun unsigned long arg)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun drm_ctx_priv_map32_t req32;
518*4882a593Smuzhiyun struct drm_ctx_priv_map request;
519*4882a593Smuzhiyun drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
522*4882a593Smuzhiyun return -EFAULT;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun request.ctx_id = req32.ctx_id;
525*4882a593Smuzhiyun request.handle = compat_ptr(req32.handle);
526*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request,
527*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
compat_drm_getsareactx(struct file * file,unsigned int cmd,unsigned long arg)530*4882a593Smuzhiyun static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
531*4882a593Smuzhiyun unsigned long arg)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun struct drm_ctx_priv_map req;
534*4882a593Smuzhiyun drm_ctx_priv_map32_t req32;
535*4882a593Smuzhiyun drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
536*4882a593Smuzhiyun int err;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
539*4882a593Smuzhiyun return -EFAULT;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun req.ctx_id = req32.ctx_id;
542*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH);
543*4882a593Smuzhiyun if (err)
544*4882a593Smuzhiyun return err;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun req32.handle = ptr_to_compat((void __user *)req.handle);
547*4882a593Smuzhiyun if (copy_to_user(argp, &req32, sizeof(req32)))
548*4882a593Smuzhiyun return -EFAULT;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun typedef struct drm_ctx_res32 {
554*4882a593Smuzhiyun int count;
555*4882a593Smuzhiyun u32 contexts;
556*4882a593Smuzhiyun } drm_ctx_res32_t;
557*4882a593Smuzhiyun
compat_drm_resctx(struct file * file,unsigned int cmd,unsigned long arg)558*4882a593Smuzhiyun static int compat_drm_resctx(struct file *file, unsigned int cmd,
559*4882a593Smuzhiyun unsigned long arg)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun drm_ctx_res32_t __user *argp = (void __user *)arg;
562*4882a593Smuzhiyun drm_ctx_res32_t res32;
563*4882a593Smuzhiyun struct drm_ctx_res res;
564*4882a593Smuzhiyun int err;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun if (copy_from_user(&res32, argp, sizeof(res32)))
567*4882a593Smuzhiyun return -EFAULT;
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun res.count = res32.count;
570*4882a593Smuzhiyun res.contexts = compat_ptr(res32.contexts);
571*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH);
572*4882a593Smuzhiyun if (err)
573*4882a593Smuzhiyun return err;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun res32.count = res.count;
576*4882a593Smuzhiyun if (copy_to_user(argp, &res32, sizeof(res32)))
577*4882a593Smuzhiyun return -EFAULT;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun return 0;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun typedef struct drm_dma32 {
583*4882a593Smuzhiyun int context; /**< Context handle */
584*4882a593Smuzhiyun int send_count; /**< Number of buffers to send */
585*4882a593Smuzhiyun u32 send_indices; /**< List of handles to buffers */
586*4882a593Smuzhiyun u32 send_sizes; /**< Lengths of data to send */
587*4882a593Smuzhiyun enum drm_dma_flags flags; /**< Flags */
588*4882a593Smuzhiyun int request_count; /**< Number of buffers requested */
589*4882a593Smuzhiyun int request_size; /**< Desired size for buffers */
590*4882a593Smuzhiyun u32 request_indices; /**< Buffer information */
591*4882a593Smuzhiyun u32 request_sizes;
592*4882a593Smuzhiyun int granted_count; /**< Number of buffers granted */
593*4882a593Smuzhiyun } drm_dma32_t;
594*4882a593Smuzhiyun
compat_drm_dma(struct file * file,unsigned int cmd,unsigned long arg)595*4882a593Smuzhiyun static int compat_drm_dma(struct file *file, unsigned int cmd,
596*4882a593Smuzhiyun unsigned long arg)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun drm_dma32_t d32;
599*4882a593Smuzhiyun drm_dma32_t __user *argp = (void __user *)arg;
600*4882a593Smuzhiyun struct drm_dma d;
601*4882a593Smuzhiyun int err;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (copy_from_user(&d32, argp, sizeof(d32)))
604*4882a593Smuzhiyun return -EFAULT;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun d.context = d32.context;
607*4882a593Smuzhiyun d.send_count = d32.send_count;
608*4882a593Smuzhiyun d.send_indices = compat_ptr(d32.send_indices);
609*4882a593Smuzhiyun d.send_sizes = compat_ptr(d32.send_sizes);
610*4882a593Smuzhiyun d.flags = d32.flags;
611*4882a593Smuzhiyun d.request_count = d32.request_count;
612*4882a593Smuzhiyun d.request_indices = compat_ptr(d32.request_indices);
613*4882a593Smuzhiyun d.request_sizes = compat_ptr(d32.request_sizes);
614*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH);
615*4882a593Smuzhiyun if (err)
616*4882a593Smuzhiyun return err;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun if (put_user(d.request_size, &argp->request_size)
619*4882a593Smuzhiyun || put_user(d.granted_count, &argp->granted_count))
620*4882a593Smuzhiyun return -EFAULT;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun return 0;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun #endif
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_AGP)
627*4882a593Smuzhiyun typedef struct drm_agp_mode32 {
628*4882a593Smuzhiyun u32 mode; /**< AGP mode */
629*4882a593Smuzhiyun } drm_agp_mode32_t;
630*4882a593Smuzhiyun
compat_drm_agp_enable(struct file * file,unsigned int cmd,unsigned long arg)631*4882a593Smuzhiyun static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
632*4882a593Smuzhiyun unsigned long arg)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun drm_agp_mode32_t __user *argp = (void __user *)arg;
635*4882a593Smuzhiyun struct drm_agp_mode mode;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun if (get_user(mode.mode, &argp->mode))
638*4882a593Smuzhiyun return -EFAULT;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_agp_enable_ioctl, &mode,
641*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun typedef struct drm_agp_info32 {
645*4882a593Smuzhiyun int agp_version_major;
646*4882a593Smuzhiyun int agp_version_minor;
647*4882a593Smuzhiyun u32 mode;
648*4882a593Smuzhiyun u32 aperture_base; /* physical address */
649*4882a593Smuzhiyun u32 aperture_size; /* bytes */
650*4882a593Smuzhiyun u32 memory_allowed; /* bytes */
651*4882a593Smuzhiyun u32 memory_used;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /* PCI information */
654*4882a593Smuzhiyun unsigned short id_vendor;
655*4882a593Smuzhiyun unsigned short id_device;
656*4882a593Smuzhiyun } drm_agp_info32_t;
657*4882a593Smuzhiyun
compat_drm_agp_info(struct file * file,unsigned int cmd,unsigned long arg)658*4882a593Smuzhiyun static int compat_drm_agp_info(struct file *file, unsigned int cmd,
659*4882a593Smuzhiyun unsigned long arg)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun drm_agp_info32_t __user *argp = (void __user *)arg;
662*4882a593Smuzhiyun drm_agp_info32_t i32;
663*4882a593Smuzhiyun struct drm_agp_info info;
664*4882a593Smuzhiyun int err;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_agp_info_ioctl, &info, DRM_AUTH);
667*4882a593Smuzhiyun if (err)
668*4882a593Smuzhiyun return err;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun i32.agp_version_major = info.agp_version_major;
671*4882a593Smuzhiyun i32.agp_version_minor = info.agp_version_minor;
672*4882a593Smuzhiyun i32.mode = info.mode;
673*4882a593Smuzhiyun i32.aperture_base = info.aperture_base;
674*4882a593Smuzhiyun i32.aperture_size = info.aperture_size;
675*4882a593Smuzhiyun i32.memory_allowed = info.memory_allowed;
676*4882a593Smuzhiyun i32.memory_used = info.memory_used;
677*4882a593Smuzhiyun i32.id_vendor = info.id_vendor;
678*4882a593Smuzhiyun i32.id_device = info.id_device;
679*4882a593Smuzhiyun if (copy_to_user(argp, &i32, sizeof(i32)))
680*4882a593Smuzhiyun return -EFAULT;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun return 0;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun typedef struct drm_agp_buffer32 {
686*4882a593Smuzhiyun u32 size; /**< In bytes -- will round to page boundary */
687*4882a593Smuzhiyun u32 handle; /**< Used for binding / unbinding */
688*4882a593Smuzhiyun u32 type; /**< Type of memory to allocate */
689*4882a593Smuzhiyun u32 physical; /**< Physical used by i810 */
690*4882a593Smuzhiyun } drm_agp_buffer32_t;
691*4882a593Smuzhiyun
compat_drm_agp_alloc(struct file * file,unsigned int cmd,unsigned long arg)692*4882a593Smuzhiyun static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
693*4882a593Smuzhiyun unsigned long arg)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun drm_agp_buffer32_t __user *argp = (void __user *)arg;
696*4882a593Smuzhiyun drm_agp_buffer32_t req32;
697*4882a593Smuzhiyun struct drm_agp_buffer request;
698*4882a593Smuzhiyun int err;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
701*4882a593Smuzhiyun return -EFAULT;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun request.size = req32.size;
704*4882a593Smuzhiyun request.type = req32.type;
705*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_agp_alloc_ioctl, &request,
706*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
707*4882a593Smuzhiyun if (err)
708*4882a593Smuzhiyun return err;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun req32.handle = request.handle;
711*4882a593Smuzhiyun req32.physical = request.physical;
712*4882a593Smuzhiyun if (copy_to_user(argp, &req32, sizeof(req32))) {
713*4882a593Smuzhiyun drm_ioctl_kernel(file, drm_agp_free_ioctl, &request,
714*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
715*4882a593Smuzhiyun return -EFAULT;
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun return 0;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun
compat_drm_agp_free(struct file * file,unsigned int cmd,unsigned long arg)721*4882a593Smuzhiyun static int compat_drm_agp_free(struct file *file, unsigned int cmd,
722*4882a593Smuzhiyun unsigned long arg)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun drm_agp_buffer32_t __user *argp = (void __user *)arg;
725*4882a593Smuzhiyun struct drm_agp_buffer request;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (get_user(request.handle, &argp->handle))
728*4882a593Smuzhiyun return -EFAULT;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_agp_free_ioctl, &request,
731*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun typedef struct drm_agp_binding32 {
735*4882a593Smuzhiyun u32 handle; /**< From drm_agp_buffer */
736*4882a593Smuzhiyun u32 offset; /**< In bytes -- will round to page boundary */
737*4882a593Smuzhiyun } drm_agp_binding32_t;
738*4882a593Smuzhiyun
compat_drm_agp_bind(struct file * file,unsigned int cmd,unsigned long arg)739*4882a593Smuzhiyun static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
740*4882a593Smuzhiyun unsigned long arg)
741*4882a593Smuzhiyun {
742*4882a593Smuzhiyun drm_agp_binding32_t __user *argp = (void __user *)arg;
743*4882a593Smuzhiyun drm_agp_binding32_t req32;
744*4882a593Smuzhiyun struct drm_agp_binding request;
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
747*4882a593Smuzhiyun return -EFAULT;
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun request.handle = req32.handle;
750*4882a593Smuzhiyun request.offset = req32.offset;
751*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_agp_bind_ioctl, &request,
752*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
compat_drm_agp_unbind(struct file * file,unsigned int cmd,unsigned long arg)755*4882a593Smuzhiyun static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
756*4882a593Smuzhiyun unsigned long arg)
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun drm_agp_binding32_t __user *argp = (void __user *)arg;
759*4882a593Smuzhiyun struct drm_agp_binding request;
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (get_user(request.handle, &argp->handle))
762*4882a593Smuzhiyun return -EFAULT;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_agp_unbind_ioctl, &request,
765*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun #endif /* CONFIG_AGP */
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
770*4882a593Smuzhiyun typedef struct drm_scatter_gather32 {
771*4882a593Smuzhiyun u32 size; /**< In bytes -- will round to page boundary */
772*4882a593Smuzhiyun u32 handle; /**< Used for mapping / unmapping */
773*4882a593Smuzhiyun } drm_scatter_gather32_t;
774*4882a593Smuzhiyun
compat_drm_sg_alloc(struct file * file,unsigned int cmd,unsigned long arg)775*4882a593Smuzhiyun static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
776*4882a593Smuzhiyun unsigned long arg)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun drm_scatter_gather32_t __user *argp = (void __user *)arg;
779*4882a593Smuzhiyun struct drm_scatter_gather request;
780*4882a593Smuzhiyun int err;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun if (get_user(request.size, &argp->size))
783*4882a593Smuzhiyun return -EFAULT;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request,
786*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
787*4882a593Smuzhiyun if (err)
788*4882a593Smuzhiyun return err;
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun /* XXX not sure about the handle conversion here... */
791*4882a593Smuzhiyun if (put_user(request.handle >> PAGE_SHIFT, &argp->handle))
792*4882a593Smuzhiyun return -EFAULT;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun return 0;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
compat_drm_sg_free(struct file * file,unsigned int cmd,unsigned long arg)797*4882a593Smuzhiyun static int compat_drm_sg_free(struct file *file, unsigned int cmd,
798*4882a593Smuzhiyun unsigned long arg)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun drm_scatter_gather32_t __user *argp = (void __user *)arg;
801*4882a593Smuzhiyun struct drm_scatter_gather request;
802*4882a593Smuzhiyun unsigned long x;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun if (get_user(x, &argp->handle))
805*4882a593Smuzhiyun return -EFAULT;
806*4882a593Smuzhiyun request.handle = x << PAGE_SHIFT;
807*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_legacy_sg_free, &request,
808*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun #endif
811*4882a593Smuzhiyun #if defined(CONFIG_X86)
812*4882a593Smuzhiyun typedef struct drm_update_draw32 {
813*4882a593Smuzhiyun drm_drawable_t handle;
814*4882a593Smuzhiyun unsigned int type;
815*4882a593Smuzhiyun unsigned int num;
816*4882a593Smuzhiyun /* 64-bit version has a 32-bit pad here */
817*4882a593Smuzhiyun u64 data; /**< Pointer */
818*4882a593Smuzhiyun } __attribute__((packed)) drm_update_draw32_t;
819*4882a593Smuzhiyun
compat_drm_update_draw(struct file * file,unsigned int cmd,unsigned long arg)820*4882a593Smuzhiyun static int compat_drm_update_draw(struct file *file, unsigned int cmd,
821*4882a593Smuzhiyun unsigned long arg)
822*4882a593Smuzhiyun {
823*4882a593Smuzhiyun drm_update_draw32_t update32;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
826*4882a593Smuzhiyun return -EFAULT;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun return drm_ioctl_kernel(file, drm_noop, NULL,
829*4882a593Smuzhiyun DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun #endif
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun struct drm_wait_vblank_request32 {
834*4882a593Smuzhiyun enum drm_vblank_seq_type type;
835*4882a593Smuzhiyun unsigned int sequence;
836*4882a593Smuzhiyun u32 signal;
837*4882a593Smuzhiyun };
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun struct drm_wait_vblank_reply32 {
840*4882a593Smuzhiyun enum drm_vblank_seq_type type;
841*4882a593Smuzhiyun unsigned int sequence;
842*4882a593Smuzhiyun s32 tval_sec;
843*4882a593Smuzhiyun s32 tval_usec;
844*4882a593Smuzhiyun };
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun typedef union drm_wait_vblank32 {
847*4882a593Smuzhiyun struct drm_wait_vblank_request32 request;
848*4882a593Smuzhiyun struct drm_wait_vblank_reply32 reply;
849*4882a593Smuzhiyun } drm_wait_vblank32_t;
850*4882a593Smuzhiyun
compat_drm_wait_vblank(struct file * file,unsigned int cmd,unsigned long arg)851*4882a593Smuzhiyun static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
852*4882a593Smuzhiyun unsigned long arg)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun drm_wait_vblank32_t __user *argp = (void __user *)arg;
855*4882a593Smuzhiyun drm_wait_vblank32_t req32;
856*4882a593Smuzhiyun union drm_wait_vblank req;
857*4882a593Smuzhiyun int err;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun if (copy_from_user(&req32, argp, sizeof(req32)))
860*4882a593Smuzhiyun return -EFAULT;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun memset(&req, 0, sizeof(req));
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun req.request.type = req32.request.type;
865*4882a593Smuzhiyun req.request.sequence = req32.request.sequence;
866*4882a593Smuzhiyun req.request.signal = req32.request.signal;
867*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun req32.reply.type = req.reply.type;
870*4882a593Smuzhiyun req32.reply.sequence = req.reply.sequence;
871*4882a593Smuzhiyun req32.reply.tval_sec = req.reply.tval_sec;
872*4882a593Smuzhiyun req32.reply.tval_usec = req.reply.tval_usec;
873*4882a593Smuzhiyun if (copy_to_user(argp, &req32, sizeof(req32)))
874*4882a593Smuzhiyun return -EFAULT;
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun return err;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun #if defined(CONFIG_X86)
880*4882a593Smuzhiyun typedef struct drm_mode_fb_cmd232 {
881*4882a593Smuzhiyun u32 fb_id;
882*4882a593Smuzhiyun u32 width;
883*4882a593Smuzhiyun u32 height;
884*4882a593Smuzhiyun u32 pixel_format;
885*4882a593Smuzhiyun u32 flags;
886*4882a593Smuzhiyun u32 handles[4];
887*4882a593Smuzhiyun u32 pitches[4];
888*4882a593Smuzhiyun u32 offsets[4];
889*4882a593Smuzhiyun u64 modifier[4];
890*4882a593Smuzhiyun } __attribute__((packed)) drm_mode_fb_cmd232_t;
891*4882a593Smuzhiyun
compat_drm_mode_addfb2(struct file * file,unsigned int cmd,unsigned long arg)892*4882a593Smuzhiyun static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
893*4882a593Smuzhiyun unsigned long arg)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg;
896*4882a593Smuzhiyun struct drm_mode_fb_cmd2 req64;
897*4882a593Smuzhiyun int err;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun memset(&req64, 0, sizeof(req64));
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun if (copy_from_user(&req64, argp,
902*4882a593Smuzhiyun offsetof(drm_mode_fb_cmd232_t, modifier)))
903*4882a593Smuzhiyun return -EFAULT;
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun if (copy_from_user(&req64.modifier, &argp->modifier,
906*4882a593Smuzhiyun sizeof(req64.modifier)))
907*4882a593Smuzhiyun return -EFAULT;
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0);
910*4882a593Smuzhiyun if (err)
911*4882a593Smuzhiyun return err;
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (put_user(req64.fb_id, &argp->fb_id))
914*4882a593Smuzhiyun return -EFAULT;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun return 0;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun #endif
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun static struct {
921*4882a593Smuzhiyun drm_ioctl_compat_t *fn;
922*4882a593Smuzhiyun char *name;
923*4882a593Smuzhiyun } drm_compat_ioctls[] = {
924*4882a593Smuzhiyun #define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n}
925*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version),
926*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique),
927*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
928*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap),
929*4882a593Smuzhiyun #endif
930*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient),
931*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats),
932*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique),
933*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
934*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap),
935*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs),
936*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs),
937*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs),
938*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs),
939*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs),
940*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap),
941*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx),
942*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx),
943*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx),
944*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma),
945*4882a593Smuzhiyun #endif
946*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_AGP)
947*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable),
948*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info),
949*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc),
950*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free),
951*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind),
952*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind),
953*4882a593Smuzhiyun #endif
954*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_LEGACY)
955*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc),
956*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free),
957*4882a593Smuzhiyun #endif
958*4882a593Smuzhiyun #if defined(CONFIG_X86) || defined(CONFIG_IA64)
959*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw),
960*4882a593Smuzhiyun #endif
961*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_WAIT_VBLANK, compat_drm_wait_vblank),
962*4882a593Smuzhiyun #if defined(CONFIG_X86) || defined(CONFIG_IA64)
963*4882a593Smuzhiyun DRM_IOCTL32_DEF(DRM_IOCTL_MODE_ADDFB2, compat_drm_mode_addfb2),
964*4882a593Smuzhiyun #endif
965*4882a593Smuzhiyun };
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun /**
968*4882a593Smuzhiyun * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
969*4882a593Smuzhiyun * @filp: file this ioctl is called on
970*4882a593Smuzhiyun * @cmd: ioctl cmd number
971*4882a593Smuzhiyun * @arg: user argument
972*4882a593Smuzhiyun *
973*4882a593Smuzhiyun * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
974*4882a593Smuzhiyun * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
975*4882a593Smuzhiyun * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
976*4882a593Smuzhiyun * botched IOCTL itself, it must handle those by wrapping this function.
977*4882a593Smuzhiyun *
978*4882a593Smuzhiyun * Returns:
979*4882a593Smuzhiyun * Zero on success, negative error code on failure.
980*4882a593Smuzhiyun */
drm_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)981*4882a593Smuzhiyun long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun unsigned int nr = DRM_IOCTL_NR(cmd);
984*4882a593Smuzhiyun struct drm_file *file_priv = filp->private_data;
985*4882a593Smuzhiyun drm_ioctl_compat_t *fn;
986*4882a593Smuzhiyun int ret;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun /* Assume that ioctls without an explicit compat routine will just
989*4882a593Smuzhiyun * work. This may not always be a good assumption, but it's better
990*4882a593Smuzhiyun * than always failing.
991*4882a593Smuzhiyun */
992*4882a593Smuzhiyun if (nr >= ARRAY_SIZE(drm_compat_ioctls))
993*4882a593Smuzhiyun return drm_ioctl(filp, cmd, arg);
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun fn = drm_compat_ioctls[nr].fn;
996*4882a593Smuzhiyun if (!fn)
997*4882a593Smuzhiyun return drm_ioctl(filp, cmd, arg);
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
1000*4882a593Smuzhiyun current->comm, task_pid_nr(current),
1001*4882a593Smuzhiyun (long)old_encode_dev(file_priv->minor->kdev->devt),
1002*4882a593Smuzhiyun file_priv->authenticated,
1003*4882a593Smuzhiyun drm_compat_ioctls[nr].name);
1004*4882a593Smuzhiyun ret = (*fn)(filp, cmd, arg);
1005*4882a593Smuzhiyun if (ret)
1006*4882a593Smuzhiyun DRM_DEBUG("ret = %d\n", ret);
1007*4882a593Smuzhiyun return ret;
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun EXPORT_SYMBOL(drm_compat_ioctl);
1010