xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/drm_ioc32.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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