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