xref: /openbmc/linux/drivers/gpu/drm/drm_ioc32.c (revision 723dad97)
12640981fSDaniel Vetter /*
2c0e09200SDave Airlie  * \file drm_ioc32.c
3c0e09200SDave Airlie  *
4c0e09200SDave Airlie  * 32-bit ioctl compatibility routines for the DRM.
5c0e09200SDave Airlie  *
6c0e09200SDave Airlie  * \author Paul Mackerras <paulus@samba.org>
7c0e09200SDave Airlie  *
8c0e09200SDave Airlie  * Copyright (C) Paul Mackerras 2005.
9c0e09200SDave Airlie  * All Rights Reserved.
10c0e09200SDave Airlie  *
11c0e09200SDave Airlie  * Permission is hereby granted, free of charge, to any person obtaining a
12c0e09200SDave Airlie  * copy of this software and associated documentation files (the "Software"),
13c0e09200SDave Airlie  * to deal in the Software without restriction, including without limitation
14c0e09200SDave Airlie  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15c0e09200SDave Airlie  * and/or sell copies of the Software, and to permit persons to whom the
16c0e09200SDave Airlie  * Software is furnished to do so, subject to the following conditions:
17c0e09200SDave Airlie  *
18c0e09200SDave Airlie  * The above copyright notice and this permission notice (including the next
19c0e09200SDave Airlie  * paragraph) shall be included in all copies or substantial portions of the
20c0e09200SDave Airlie  * Software.
21c0e09200SDave Airlie  *
22c0e09200SDave Airlie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c0e09200SDave Airlie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c0e09200SDave Airlie  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25c0e09200SDave Airlie  * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26c0e09200SDave Airlie  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27c0e09200SDave Airlie  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28c0e09200SDave Airlie  * IN THE SOFTWARE.
29c0e09200SDave Airlie  */
30c0e09200SDave Airlie #include <linux/compat.h>
31cafe8d84SChristian Dietrich #include <linux/ratelimit.h>
322d1a8a48SPaul Gortmaker #include <linux/export.h>
33c0e09200SDave Airlie 
340500c04eSSam Ravnborg #include <drm/drm_file.h>
350500c04eSSam Ravnborg #include <drm/drm_print.h>
360500c04eSSam Ravnborg 
37d6c56613SAl Viro #include "drm_crtc_internal.h"
380500c04eSSam Ravnborg #include "drm_internal.h"
390500c04eSSam Ravnborg #include "drm_legacy.h"
40c0e09200SDave Airlie 
41c0e09200SDave Airlie #define DRM_IOCTL_VERSION32		DRM_IOWR(0x00, drm_version32_t)
42c0e09200SDave Airlie #define DRM_IOCTL_GET_UNIQUE32		DRM_IOWR(0x01, drm_unique32_t)
43c0e09200SDave Airlie #define DRM_IOCTL_GET_MAP32		DRM_IOWR(0x04, drm_map32_t)
44c0e09200SDave Airlie #define DRM_IOCTL_GET_CLIENT32		DRM_IOWR(0x05, drm_client32_t)
45c0e09200SDave Airlie #define DRM_IOCTL_GET_STATS32		DRM_IOR( 0x06, drm_stats32_t)
46c0e09200SDave Airlie 
47c0e09200SDave Airlie #define DRM_IOCTL_SET_UNIQUE32		DRM_IOW( 0x10, drm_unique32_t)
48c0e09200SDave Airlie #define DRM_IOCTL_ADD_MAP32		DRM_IOWR(0x15, drm_map32_t)
49c0e09200SDave Airlie #define DRM_IOCTL_ADD_BUFS32		DRM_IOWR(0x16, drm_buf_desc32_t)
50c0e09200SDave Airlie #define DRM_IOCTL_MARK_BUFS32		DRM_IOW( 0x17, drm_buf_desc32_t)
51c0e09200SDave Airlie #define DRM_IOCTL_INFO_BUFS32		DRM_IOWR(0x18, drm_buf_info32_t)
52c0e09200SDave Airlie #define DRM_IOCTL_MAP_BUFS32		DRM_IOWR(0x19, drm_buf_map32_t)
53c0e09200SDave Airlie #define DRM_IOCTL_FREE_BUFS32		DRM_IOW( 0x1a, drm_buf_free32_t)
54c0e09200SDave Airlie 
55c0e09200SDave Airlie #define DRM_IOCTL_RM_MAP32		DRM_IOW( 0x1b, drm_map32_t)
56c0e09200SDave Airlie 
57c0e09200SDave Airlie #define DRM_IOCTL_SET_SAREA_CTX32	DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
58c0e09200SDave Airlie #define DRM_IOCTL_GET_SAREA_CTX32	DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
59c0e09200SDave Airlie 
60c0e09200SDave Airlie #define DRM_IOCTL_RES_CTX32		DRM_IOWR(0x26, drm_ctx_res32_t)
61c0e09200SDave Airlie #define DRM_IOCTL_DMA32			DRM_IOWR(0x29, drm_dma32_t)
62c0e09200SDave Airlie 
63c0e09200SDave Airlie #define DRM_IOCTL_AGP_ENABLE32		DRM_IOW( 0x32, drm_agp_mode32_t)
64c0e09200SDave Airlie #define DRM_IOCTL_AGP_INFO32		DRM_IOR( 0x33, drm_agp_info32_t)
65c0e09200SDave Airlie #define DRM_IOCTL_AGP_ALLOC32		DRM_IOWR(0x34, drm_agp_buffer32_t)
66c0e09200SDave Airlie #define DRM_IOCTL_AGP_FREE32		DRM_IOW( 0x35, drm_agp_buffer32_t)
67c0e09200SDave Airlie #define DRM_IOCTL_AGP_BIND32		DRM_IOW( 0x36, drm_agp_binding32_t)
68c0e09200SDave Airlie #define DRM_IOCTL_AGP_UNBIND32		DRM_IOW( 0x37, drm_agp_binding32_t)
69c0e09200SDave Airlie 
70c0e09200SDave Airlie #define DRM_IOCTL_SG_ALLOC32		DRM_IOW( 0x38, drm_scatter_gather32_t)
71c0e09200SDave Airlie #define DRM_IOCTL_SG_FREE32		DRM_IOW( 0x39, drm_scatter_gather32_t)
72c0e09200SDave Airlie 
7349568873SEric Anholt #define DRM_IOCTL_UPDATE_DRAW32		DRM_IOW( 0x3f, drm_update_draw32_t)
7449568873SEric Anholt 
75c0e09200SDave Airlie #define DRM_IOCTL_WAIT_VBLANK32		DRM_IOWR(0x3a, drm_wait_vblank32_t)
76c0e09200SDave Airlie 
77c631d5f9STvrtko Ursulin #define DRM_IOCTL_MODE_ADDFB232		DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
78c631d5f9STvrtko Ursulin 
79c0e09200SDave Airlie typedef struct drm_version_32 {
802640981fSDaniel Vetter 	int version_major;	  /* Major version */
812640981fSDaniel Vetter 	int version_minor;	  /* Minor version */
822640981fSDaniel Vetter 	int version_patchlevel;	   /* Patch level */
832640981fSDaniel Vetter 	u32 name_len;		  /* Length of name buffer */
842640981fSDaniel Vetter 	u32 name;		  /* Name of driver */
852640981fSDaniel Vetter 	u32 date_len;		  /* Length of date buffer */
862640981fSDaniel Vetter 	u32 date;		  /* User-space buffer to hold date */
872640981fSDaniel Vetter 	u32 desc_len;		  /* Length of desc buffer */
882640981fSDaniel Vetter 	u32 desc;		  /* User-space buffer to hold desc */
89c0e09200SDave Airlie } drm_version32_t;
90c0e09200SDave Airlie 
compat_drm_version(struct file * file,unsigned int cmd,unsigned long arg)91c0e09200SDave Airlie static int compat_drm_version(struct file *file, unsigned int cmd,
92c0e09200SDave Airlie 			      unsigned long arg)
93c0e09200SDave Airlie {
94c0e09200SDave Airlie 	drm_version32_t v32;
95012c6741SAl Viro 	struct drm_version v;
96c0e09200SDave Airlie 	int err;
97c0e09200SDave Airlie 
98c0e09200SDave Airlie 	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
99c0e09200SDave Airlie 		return -EFAULT;
100c0e09200SDave Airlie 
101e926c474SDaniel Vetter 	memset(&v, 0, sizeof(v));
102e926c474SDaniel Vetter 
103012c6741SAl Viro 	v = (struct drm_version) {
104012c6741SAl Viro 		.name_len = v32.name_len,
105012c6741SAl Viro 		.name = compat_ptr(v32.name),
106012c6741SAl Viro 		.date_len = v32.date_len,
107012c6741SAl Viro 		.date = compat_ptr(v32.date),
108012c6741SAl Viro 		.desc_len = v32.desc_len,
109012c6741SAl Viro 		.desc = compat_ptr(v32.desc),
110012c6741SAl Viro 	};
111012c6741SAl Viro 	err = drm_ioctl_kernel(file, drm_version, &v,
11275426367SDaniel Vetter 			       DRM_RENDER_ALLOW);
113c0e09200SDave Airlie 	if (err)
114c0e09200SDave Airlie 		return err;
115c0e09200SDave Airlie 
116012c6741SAl Viro 	v32.version_major = v.version_major;
117012c6741SAl Viro 	v32.version_minor = v.version_minor;
118012c6741SAl Viro 	v32.version_patchlevel = v.version_patchlevel;
119266530b3SJeffy Chen 	v32.name_len = v.name_len;
120266530b3SJeffy Chen 	v32.date_len = v.date_len;
121266530b3SJeffy Chen 	v32.desc_len = v.desc_len;
122c0e09200SDave Airlie 	if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
123c0e09200SDave Airlie 		return -EFAULT;
124c0e09200SDave Airlie 	return 0;
125c0e09200SDave Airlie }
126c0e09200SDave Airlie 
127c0e09200SDave Airlie typedef struct drm_unique32 {
1282640981fSDaniel Vetter 	u32 unique_len;	/* Length of unique */
1292640981fSDaniel Vetter 	u32 unique;	/* Unique name for driver instantiation */
130c0e09200SDave Airlie } drm_unique32_t;
131c0e09200SDave Airlie 
compat_drm_getunique(struct file * file,unsigned int cmd,unsigned long arg)132c0e09200SDave Airlie static int compat_drm_getunique(struct file *file, unsigned int cmd,
133c0e09200SDave Airlie 				unsigned long arg)
134c0e09200SDave Airlie {
135c0e09200SDave Airlie 	drm_unique32_t uq32;
13617e3dadeSAl Viro 	struct drm_unique uq;
137c0e09200SDave Airlie 	int err;
138c0e09200SDave Airlie 
139c0e09200SDave Airlie 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
140c0e09200SDave Airlie 		return -EFAULT;
141e926c474SDaniel Vetter 
142e926c474SDaniel Vetter 	memset(&uq, 0, sizeof(uq));
143e926c474SDaniel Vetter 
14417e3dadeSAl Viro 	uq = (struct drm_unique){
14517e3dadeSAl Viro 		.unique_len = uq32.unique_len,
14617e3dadeSAl Viro 		.unique = compat_ptr(uq32.unique),
14717e3dadeSAl Viro 	};
148c0e09200SDave Airlie 
14975426367SDaniel Vetter 	err = drm_ioctl_kernel(file, drm_getunique, &uq, 0);
150c0e09200SDave Airlie 	if (err)
151c0e09200SDave Airlie 		return err;
152c0e09200SDave Airlie 
15317e3dadeSAl Viro 	uq32.unique_len = uq.unique_len;
154c0e09200SDave Airlie 	if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
155c0e09200SDave Airlie 		return -EFAULT;
156c0e09200SDave Airlie 	return 0;
157c0e09200SDave Airlie }
158c0e09200SDave Airlie 
compat_drm_setunique(struct file * file,unsigned int cmd,unsigned long arg)159c0e09200SDave Airlie static int compat_drm_setunique(struct file *file, unsigned int cmd,
160c0e09200SDave Airlie 				unsigned long arg)
161c0e09200SDave Airlie {
16256c275ccSAl Viro 	/* it's dead */
16356c275ccSAl Viro 	return -EINVAL;
164c0e09200SDave Airlie }
165c0e09200SDave Airlie 
16661ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
167c0e09200SDave Airlie typedef struct drm_map32 {
1682640981fSDaniel Vetter 	u32 offset;		/* Requested physical address (0 for SAREA) */
1692640981fSDaniel Vetter 	u32 size;		/* Requested physical size (bytes) */
1702640981fSDaniel Vetter 	enum drm_map_type type;	/* Type of memory to map */
1712640981fSDaniel Vetter 	enum drm_map_flags flags;	/* Flags */
1722640981fSDaniel Vetter 	u32 handle;		/* User-space: "Handle" to pass to mmap() */
1732640981fSDaniel Vetter 	int mtrr;		/* MTRR slot used */
174c0e09200SDave Airlie } drm_map32_t;
175c0e09200SDave Airlie 
compat_drm_getmap(struct file * file,unsigned int cmd,unsigned long arg)176c0e09200SDave Airlie static int compat_drm_getmap(struct file *file, unsigned int cmd,
177c0e09200SDave Airlie 			     unsigned long arg)
178c0e09200SDave Airlie {
179c0e09200SDave Airlie 	drm_map32_t __user *argp = (void __user *)arg;
180c0e09200SDave Airlie 	drm_map32_t m32;
1818c4fe499SAl Viro 	struct drm_map map;
1828c4fe499SAl Viro 	int err;
183c0e09200SDave Airlie 
1848c4fe499SAl Viro 	if (copy_from_user(&m32, argp, sizeof(m32)))
185c0e09200SDave Airlie 		return -EFAULT;
186c0e09200SDave Airlie 
1878c4fe499SAl Viro 	map.offset = m32.offset;
18875426367SDaniel Vetter 	err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0);
189c0e09200SDave Airlie 	if (err)
190c0e09200SDave Airlie 		return err;
191c0e09200SDave Airlie 
1928c4fe499SAl Viro 	m32.offset = map.offset;
1938c4fe499SAl Viro 	m32.size = map.size;
1948c4fe499SAl Viro 	m32.type = map.type;
1958c4fe499SAl Viro 	m32.flags = map.flags;
196e552f085SBen Dooks 	m32.handle = ptr_to_compat((void __user *)map.handle);
1978c4fe499SAl Viro 	m32.mtrr = map.mtrr;
198c0e09200SDave Airlie 	if (copy_to_user(argp, &m32, sizeof(m32)))
199c0e09200SDave Airlie 		return -EFAULT;
200c0e09200SDave Airlie 	return 0;
201c0e09200SDave Airlie 
202c0e09200SDave Airlie }
203c0e09200SDave Airlie 
compat_drm_addmap(struct file * file,unsigned int cmd,unsigned long arg)204c0e09200SDave Airlie static int compat_drm_addmap(struct file *file, unsigned int cmd,
205c0e09200SDave Airlie 			     unsigned long arg)
206c0e09200SDave Airlie {
207c0e09200SDave Airlie 	drm_map32_t __user *argp = (void __user *)arg;
208c0e09200SDave Airlie 	drm_map32_t m32;
209b36180a3SAl Viro 	struct drm_map map;
210c0e09200SDave Airlie 	int err;
211c0e09200SDave Airlie 
212c0e09200SDave Airlie 	if (copy_from_user(&m32, argp, sizeof(m32)))
213c0e09200SDave Airlie 		return -EFAULT;
214c0e09200SDave Airlie 
215b36180a3SAl Viro 	map.offset = m32.offset;
216b36180a3SAl Viro 	map.size = m32.size;
217b36180a3SAl Viro 	map.type = m32.type;
218b36180a3SAl Viro 	map.flags = m32.flags;
219c0e09200SDave Airlie 
220b36180a3SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map,
221b36180a3SAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
222c0e09200SDave Airlie 	if (err)
223c0e09200SDave Airlie 		return err;
224c0e09200SDave Airlie 
225b36180a3SAl Viro 	m32.offset = map.offset;
226b36180a3SAl Viro 	m32.mtrr = map.mtrr;
227e552f085SBen Dooks 	m32.handle = ptr_to_compat((void __user *)map.handle);
228b36180a3SAl Viro 	if (map.handle != compat_ptr(m32.handle))
229499447dbSJoe Perches 		pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n",
230b36180a3SAl Viro 				   map.handle, m32.type, m32.offset);
231c0e09200SDave Airlie 
232c0e09200SDave Airlie 	if (copy_to_user(argp, &m32, sizeof(m32)))
233c0e09200SDave Airlie 		return -EFAULT;
234c0e09200SDave Airlie 
235c0e09200SDave Airlie 	return 0;
236c0e09200SDave Airlie }
237c0e09200SDave Airlie 
compat_drm_rmmap(struct file * file,unsigned int cmd,unsigned long arg)238c0e09200SDave Airlie static int compat_drm_rmmap(struct file *file, unsigned int cmd,
239c0e09200SDave Airlie 			    unsigned long arg)
240c0e09200SDave Airlie {
241c0e09200SDave Airlie 	drm_map32_t __user *argp = (void __user *)arg;
2426113252dSAl Viro 	struct drm_map map;
243c0e09200SDave Airlie 	u32 handle;
244c0e09200SDave Airlie 
245c0e09200SDave Airlie 	if (get_user(handle, &argp->handle))
246c0e09200SDave Airlie 		return -EFAULT;
2476113252dSAl Viro 	map.handle = compat_ptr(handle);
2486113252dSAl Viro 	return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH);
249c0e09200SDave Airlie }
25061ae2270SDave Airlie #endif
251c0e09200SDave Airlie 
252c0e09200SDave Airlie typedef struct drm_client32 {
2532640981fSDaniel Vetter 	int idx;	/* Which client desired? */
2542640981fSDaniel Vetter 	int auth;	/* Is client authenticated? */
2552640981fSDaniel Vetter 	u32 pid;	/* Process ID */
2562640981fSDaniel Vetter 	u32 uid;	/* User ID */
2572640981fSDaniel Vetter 	u32 magic;	/* Magic */
2582640981fSDaniel Vetter 	u32 iocs;	/* Ioctl count */
259c0e09200SDave Airlie } drm_client32_t;
260c0e09200SDave Airlie 
compat_drm_getclient(struct file * file,unsigned int cmd,unsigned long arg)261c0e09200SDave Airlie static int compat_drm_getclient(struct file *file, unsigned int cmd,
262c0e09200SDave Airlie 				unsigned long arg)
263c0e09200SDave Airlie {
264c0e09200SDave Airlie 	drm_client32_t c32;
265c0e09200SDave Airlie 	drm_client32_t __user *argp = (void __user *)arg;
2669e92662dSAl Viro 	struct drm_client client;
2679e92662dSAl Viro 	int err;
268c0e09200SDave Airlie 
2699e92662dSAl Viro 	if (copy_from_user(&c32, argp, sizeof(c32)))
270c0e09200SDave Airlie 		return -EFAULT;
271c0e09200SDave Airlie 
272e926c474SDaniel Vetter 	memset(&client, 0, sizeof(client));
273e926c474SDaniel Vetter 
2749e92662dSAl Viro 	client.idx = c32.idx;
275c0e09200SDave Airlie 
27675426367SDaniel Vetter 	err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
277c0e09200SDave Airlie 	if (err)
278c0e09200SDave Airlie 		return err;
279c0e09200SDave Airlie 
2809e92662dSAl Viro 	c32.idx = client.idx;
2819e92662dSAl Viro 	c32.auth = client.auth;
2829e92662dSAl Viro 	c32.pid = client.pid;
2839e92662dSAl Viro 	c32.uid = client.uid;
2849e92662dSAl Viro 	c32.magic = client.magic;
2859e92662dSAl Viro 	c32.iocs = client.iocs;
286c0e09200SDave Airlie 
287c0e09200SDave Airlie 	if (copy_to_user(argp, &c32, sizeof(c32)))
288c0e09200SDave Airlie 		return -EFAULT;
289c0e09200SDave Airlie 	return 0;
290c0e09200SDave Airlie }
291c0e09200SDave Airlie 
292c0e09200SDave Airlie typedef struct drm_stats32 {
293c0e09200SDave Airlie 	u32 count;
294c0e09200SDave Airlie 	struct {
295c0e09200SDave Airlie 		u32 value;
296c0e09200SDave Airlie 		enum drm_stat_type type;
297c0e09200SDave Airlie 	} data[15];
298c0e09200SDave Airlie } drm_stats32_t;
299c0e09200SDave Airlie 
compat_drm_getstats(struct file * file,unsigned int cmd,unsigned long arg)300c0e09200SDave Airlie static int compat_drm_getstats(struct file *file, unsigned int cmd,
301c0e09200SDave Airlie 			       unsigned long arg)
302c0e09200SDave Airlie {
303c0e09200SDave Airlie 	drm_stats32_t __user *argp = (void __user *)arg;
304c0e09200SDave Airlie 
3052da9a1a2SDaniel Vetter 	/* getstats is defunct, just clear */
3068547ee9dSAl Viro 	if (clear_user(argp, sizeof(drm_stats32_t)))
307c0e09200SDave Airlie 		return -EFAULT;
308c0e09200SDave Airlie 	return 0;
309c0e09200SDave Airlie }
310c0e09200SDave Airlie 
31161ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
312c0e09200SDave Airlie typedef struct drm_buf_desc32 {
3132640981fSDaniel Vetter 	int count;		 /* Number of buffers of this size */
3142640981fSDaniel Vetter 	int size;		 /* Size in bytes */
3152640981fSDaniel Vetter 	int low_mark;		 /* Low water mark */
3162640981fSDaniel Vetter 	int high_mark;		 /* High water mark */
317c0e09200SDave Airlie 	int flags;
3182640981fSDaniel Vetter 	u32 agp_start;		 /* Start address in the AGP aperture */
319c0e09200SDave Airlie } drm_buf_desc32_t;
320c0e09200SDave Airlie 
compat_drm_addbufs(struct file * file,unsigned int cmd,unsigned long arg)321c0e09200SDave Airlie static int compat_drm_addbufs(struct file *file, unsigned int cmd,
322c0e09200SDave Airlie 			      unsigned long arg)
323c0e09200SDave Airlie {
324c0e09200SDave Airlie 	drm_buf_desc32_t __user *argp = (void __user *)arg;
325ff22ff9eSAl Viro 	drm_buf_desc32_t desc32;
326ff22ff9eSAl Viro 	struct drm_buf_desc desc;
327c0e09200SDave Airlie 	int err;
328c0e09200SDave Airlie 
329ff22ff9eSAl Viro 	if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t)))
330c0e09200SDave Airlie 		return -EFAULT;
331c0e09200SDave Airlie 
332ff22ff9eSAl Viro 	desc = (struct drm_buf_desc){
333ff22ff9eSAl Viro 		desc32.count, desc32.size, desc32.low_mark, desc32.high_mark,
334ff22ff9eSAl Viro 		desc32.flags, desc32.agp_start
335ff22ff9eSAl Viro 	};
336c0e09200SDave Airlie 
337ff22ff9eSAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc,
338ff22ff9eSAl Viro 				   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
339c0e09200SDave Airlie 	if (err)
340c0e09200SDave Airlie 		return err;
341c0e09200SDave Airlie 
342ff22ff9eSAl Viro 	desc32 = (drm_buf_desc32_t){
343ff22ff9eSAl Viro 		desc.count, desc.size, desc.low_mark, desc.high_mark,
344ff22ff9eSAl Viro 		desc.flags, desc.agp_start
345ff22ff9eSAl Viro 	};
346ff22ff9eSAl Viro 	if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t)))
347c0e09200SDave Airlie 		return -EFAULT;
348c0e09200SDave Airlie 
349c0e09200SDave Airlie 	return 0;
350c0e09200SDave Airlie }
351c0e09200SDave Airlie 
compat_drm_markbufs(struct file * file,unsigned int cmd,unsigned long arg)352c0e09200SDave Airlie static int compat_drm_markbufs(struct file *file, unsigned int cmd,
353c0e09200SDave Airlie 			       unsigned long arg)
354c0e09200SDave Airlie {
355c0e09200SDave Airlie 	drm_buf_desc32_t b32;
356c0e09200SDave Airlie 	drm_buf_desc32_t __user *argp = (void __user *)arg;
357b87b786bSAl Viro 	struct drm_buf_desc buf;
358c0e09200SDave Airlie 
359c0e09200SDave Airlie 	if (copy_from_user(&b32, argp, sizeof(b32)))
360c0e09200SDave Airlie 		return -EFAULT;
361c0e09200SDave Airlie 
362dbae740eSAl Viro 	buf.size = b32.size;
363dbae740eSAl Viro 	buf.low_mark = b32.low_mark;
364dbae740eSAl Viro 	buf.high_mark = b32.high_mark;
365c0e09200SDave Airlie 
366dbae740eSAl Viro 	return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf,
367dbae740eSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
368c0e09200SDave Airlie }
369c0e09200SDave Airlie 
370c0e09200SDave Airlie typedef struct drm_buf_info32 {
371c0e09200SDave Airlie 	int count;		/**< Entries in list */
372c0e09200SDave Airlie 	u32 list;
373c0e09200SDave Airlie } drm_buf_info32_t;
374c0e09200SDave Airlie 
copy_one_buf32(void * data,int count,struct drm_buf_entry * from)3755c7640abSAl Viro static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from)
3765c7640abSAl Viro {
3775c7640abSAl Viro 	drm_buf_info32_t *request = data;
3785c7640abSAl Viro 	drm_buf_desc32_t __user *to = compat_ptr(request->list);
3795c7640abSAl Viro 	drm_buf_desc32_t v = {.count = from->buf_count,
3805c7640abSAl Viro 			      .size = from->buf_size,
3815c7640abSAl Viro 			      .low_mark = from->low_mark,
3825c7640abSAl Viro 			      .high_mark = from->high_mark};
38374b67efaSDan Carpenter 
38474b67efaSDan Carpenter 	if (copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)))
38574b67efaSDan Carpenter 		return -EFAULT;
38674b67efaSDan Carpenter 	return 0;
3875c7640abSAl Viro }
3885c7640abSAl Viro 
drm_legacy_infobufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)3895c7640abSAl Viro static int drm_legacy_infobufs32(struct drm_device *dev, void *data,
3905c7640abSAl Viro 			struct drm_file *file_priv)
3915c7640abSAl Viro {
3925c7640abSAl Viro 	drm_buf_info32_t *request = data;
393948de842SSuraj Upadhyay 
3945c7640abSAl Viro 	return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32);
3955c7640abSAl Viro }
3965c7640abSAl Viro 
compat_drm_infobufs(struct file * file,unsigned int cmd,unsigned long arg)397c0e09200SDave Airlie static int compat_drm_infobufs(struct file *file, unsigned int cmd,
398c0e09200SDave Airlie 			       unsigned long arg)
399c0e09200SDave Airlie {
400c0e09200SDave Airlie 	drm_buf_info32_t req32;
401c0e09200SDave Airlie 	drm_buf_info32_t __user *argp = (void __user *)arg;
4025c7640abSAl Viro 	int err;
403c0e09200SDave Airlie 
404c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
405c0e09200SDave Airlie 		return -EFAULT;
406c0e09200SDave Airlie 
4075c7640abSAl Viro 	if (req32.count < 0)
4085c7640abSAl Viro 		req32.count = 0;
409c0e09200SDave Airlie 
4105c7640abSAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH);
411c0e09200SDave Airlie 	if (err)
412c0e09200SDave Airlie 		return err;
413c0e09200SDave Airlie 
4145c7640abSAl Viro 	if (put_user(req32.count, &argp->count))
415c0e09200SDave Airlie 		return -EFAULT;
416c0e09200SDave Airlie 
417c0e09200SDave Airlie 	return 0;
418c0e09200SDave Airlie }
419c0e09200SDave Airlie 
420c0e09200SDave Airlie typedef struct drm_buf_pub32 {
421c0e09200SDave Airlie 	int idx;		/**< Index into the master buffer list */
422c0e09200SDave Airlie 	int total;		/**< Buffer size */
423c0e09200SDave Airlie 	int used;		/**< Amount of buffer in use (for DMA) */
424c0e09200SDave Airlie 	u32 address;		/**< Address of buffer */
425c0e09200SDave Airlie } drm_buf_pub32_t;
426c0e09200SDave Airlie 
427c0e09200SDave Airlie typedef struct drm_buf_map32 {
428c0e09200SDave Airlie 	int count;		/**< Length of the buffer list */
429c0e09200SDave Airlie 	u32 virtual;		/**< Mmap'd area in user-virtual */
430c0e09200SDave Airlie 	u32 list;		/**< Buffer information */
431c0e09200SDave Airlie } drm_buf_map32_t;
432c0e09200SDave Airlie 
map_one_buf32(void * data,int idx,unsigned long virtual,struct drm_buf * buf)43387d3ce11SAl Viro static int map_one_buf32(void *data, int idx, unsigned long virtual,
43487d3ce11SAl Viro 			struct drm_buf *buf)
43587d3ce11SAl Viro {
43687d3ce11SAl Viro 	drm_buf_map32_t *request = data;
43787d3ce11SAl Viro 	drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx;
43887d3ce11SAl Viro 	drm_buf_pub32_t v;
43987d3ce11SAl Viro 
44087d3ce11SAl Viro 	v.idx = buf->idx;
44187d3ce11SAl Viro 	v.total = buf->total;
44287d3ce11SAl Viro 	v.used = 0;
44387d3ce11SAl Viro 	v.address = virtual + buf->offset;
44487d3ce11SAl Viro 	if (copy_to_user(to, &v, sizeof(v)))
44587d3ce11SAl Viro 		return -EFAULT;
44687d3ce11SAl Viro 	return 0;
44787d3ce11SAl Viro }
44887d3ce11SAl Viro 
drm_legacy_mapbufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)44987d3ce11SAl Viro static int drm_legacy_mapbufs32(struct drm_device *dev, void *data,
45087d3ce11SAl Viro 		       struct drm_file *file_priv)
45187d3ce11SAl Viro {
45287d3ce11SAl Viro 	drm_buf_map32_t *request = data;
45387d3ce11SAl Viro 	void __user *v;
45487d3ce11SAl Viro 	int err = __drm_legacy_mapbufs(dev, data, &request->count,
45587d3ce11SAl Viro 				    &v, map_one_buf32,
45687d3ce11SAl Viro 				    file_priv);
45787d3ce11SAl Viro 	request->virtual = ptr_to_compat(v);
45887d3ce11SAl Viro 	return err;
45987d3ce11SAl Viro }
46087d3ce11SAl Viro 
compat_drm_mapbufs(struct file * file,unsigned int cmd,unsigned long arg)461c0e09200SDave Airlie static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
462c0e09200SDave Airlie 			      unsigned long arg)
463c0e09200SDave Airlie {
464c0e09200SDave Airlie 	drm_buf_map32_t __user *argp = (void __user *)arg;
465c0e09200SDave Airlie 	drm_buf_map32_t req32;
46687d3ce11SAl Viro 	int err;
467c0e09200SDave Airlie 
468c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
469c0e09200SDave Airlie 		return -EFAULT;
47087d3ce11SAl Viro 	if (req32.count < 0)
471c0e09200SDave Airlie 		return -EINVAL;
472c0e09200SDave Airlie 
47387d3ce11SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH);
474c0e09200SDave Airlie 	if (err)
475c0e09200SDave Airlie 		return err;
476c0e09200SDave Airlie 
47787d3ce11SAl Viro 	if (put_user(req32.count, &argp->count)
47887d3ce11SAl Viro 	    || put_user(req32.virtual, &argp->virtual))
479c0e09200SDave Airlie 		return -EFAULT;
480c0e09200SDave Airlie 
481c0e09200SDave Airlie 	return 0;
482c0e09200SDave Airlie }
483c0e09200SDave Airlie 
484c0e09200SDave Airlie typedef struct drm_buf_free32 {
485c0e09200SDave Airlie 	int count;
486c0e09200SDave Airlie 	u32 list;
487c0e09200SDave Airlie } drm_buf_free32_t;
488c0e09200SDave Airlie 
compat_drm_freebufs(struct file * file,unsigned int cmd,unsigned long arg)489c0e09200SDave Airlie static int compat_drm_freebufs(struct file *file, unsigned int cmd,
490c0e09200SDave Airlie 			       unsigned long arg)
491c0e09200SDave Airlie {
492c0e09200SDave Airlie 	drm_buf_free32_t req32;
4938c9e4cfbSAl Viro 	struct drm_buf_free request;
494c0e09200SDave Airlie 	drm_buf_free32_t __user *argp = (void __user *)arg;
495c0e09200SDave Airlie 
496c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
497c0e09200SDave Airlie 		return -EFAULT;
498c0e09200SDave Airlie 
4998c9e4cfbSAl Viro 	request.count = req32.count;
5008c9e4cfbSAl Viro 	request.list = compat_ptr(req32.list);
5018c9e4cfbSAl Viro 	return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH);
502c0e09200SDave Airlie }
503c0e09200SDave Airlie 
504c0e09200SDave Airlie typedef struct drm_ctx_priv_map32 {
505c0e09200SDave Airlie 	unsigned int ctx_id;	 /**< Context requesting private mapping */
506c0e09200SDave Airlie 	u32 handle;		/**< Handle of map */
507c0e09200SDave Airlie } drm_ctx_priv_map32_t;
508c0e09200SDave Airlie 
compat_drm_setsareactx(struct file * file,unsigned int cmd,unsigned long arg)509c0e09200SDave Airlie static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
510c0e09200SDave Airlie 				  unsigned long arg)
511c0e09200SDave Airlie {
512c0e09200SDave Airlie 	drm_ctx_priv_map32_t req32;
5137900c600SAl Viro 	struct drm_ctx_priv_map request;
514c0e09200SDave Airlie 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
515c0e09200SDave Airlie 
516c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
517c0e09200SDave Airlie 		return -EFAULT;
518c0e09200SDave Airlie 
5197900c600SAl Viro 	request.ctx_id = req32.ctx_id;
5207900c600SAl Viro 	request.handle = compat_ptr(req32.handle);
5217900c600SAl Viro 	return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request,
5227900c600SAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
523c0e09200SDave Airlie }
524c0e09200SDave Airlie 
compat_drm_getsareactx(struct file * file,unsigned int cmd,unsigned long arg)525c0e09200SDave Airlie static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
526c0e09200SDave Airlie 				  unsigned long arg)
527c0e09200SDave Airlie {
528d7631e30SAl Viro 	struct drm_ctx_priv_map req;
529d7631e30SAl Viro 	drm_ctx_priv_map32_t req32;
530c0e09200SDave Airlie 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
531c0e09200SDave Airlie 	int err;
532c0e09200SDave Airlie 
533d7631e30SAl Viro 	if (copy_from_user(&req32, argp, sizeof(req32)))
534c0e09200SDave Airlie 		return -EFAULT;
535c0e09200SDave Airlie 
536d7631e30SAl Viro 	req.ctx_id = req32.ctx_id;
537d7631e30SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH);
538c0e09200SDave Airlie 	if (err)
539c0e09200SDave Airlie 		return err;
540c0e09200SDave Airlie 
541e552f085SBen Dooks 	req32.handle = ptr_to_compat((void __user *)req.handle);
542d7631e30SAl Viro 	if (copy_to_user(argp, &req32, sizeof(req32)))
543c0e09200SDave Airlie 		return -EFAULT;
544c0e09200SDave Airlie 
545c0e09200SDave Airlie 	return 0;
546c0e09200SDave Airlie }
547c0e09200SDave Airlie 
548c0e09200SDave Airlie typedef struct drm_ctx_res32 {
549c0e09200SDave Airlie 	int count;
550c0e09200SDave Airlie 	u32 contexts;
551c0e09200SDave Airlie } drm_ctx_res32_t;
552c0e09200SDave Airlie 
compat_drm_resctx(struct file * file,unsigned int cmd,unsigned long arg)553c0e09200SDave Airlie static int compat_drm_resctx(struct file *file, unsigned int cmd,
554c0e09200SDave Airlie 			     unsigned long arg)
555c0e09200SDave Airlie {
556c0e09200SDave Airlie 	drm_ctx_res32_t __user *argp = (void __user *)arg;
557c0e09200SDave Airlie 	drm_ctx_res32_t res32;
5589e075680SAl Viro 	struct drm_ctx_res res;
559c0e09200SDave Airlie 	int err;
560c0e09200SDave Airlie 
561c0e09200SDave Airlie 	if (copy_from_user(&res32, argp, sizeof(res32)))
562c0e09200SDave Airlie 		return -EFAULT;
563c0e09200SDave Airlie 
5649e075680SAl Viro 	res.count = res32.count;
5659e075680SAl Viro 	res.contexts = compat_ptr(res32.contexts);
5669e075680SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH);
567c0e09200SDave Airlie 	if (err)
568c0e09200SDave Airlie 		return err;
569c0e09200SDave Airlie 
5709e075680SAl Viro 	res32.count = res.count;
5719e075680SAl Viro 	if (copy_to_user(argp, &res32, sizeof(res32)))
572c0e09200SDave Airlie 		return -EFAULT;
573c0e09200SDave Airlie 
574c0e09200SDave Airlie 	return 0;
575c0e09200SDave Airlie }
576c0e09200SDave Airlie 
577c0e09200SDave Airlie typedef struct drm_dma32 {
578c0e09200SDave Airlie 	int context;		  /**< Context handle */
579c0e09200SDave Airlie 	int send_count;		  /**< Number of buffers to send */
580c0e09200SDave Airlie 	u32 send_indices;	  /**< List of handles to buffers */
581c0e09200SDave Airlie 	u32 send_sizes;		  /**< Lengths of data to send */
582c0e09200SDave Airlie 	enum drm_dma_flags flags;		  /**< Flags */
583c0e09200SDave Airlie 	int request_count;	  /**< Number of buffers requested */
584c0e09200SDave Airlie 	int request_size;	  /**< Desired size for buffers */
585c0e09200SDave Airlie 	u32 request_indices;	  /**< Buffer information */
586c0e09200SDave Airlie 	u32 request_sizes;
587c0e09200SDave Airlie 	int granted_count;	  /**< Number of buffers granted */
588c0e09200SDave Airlie } drm_dma32_t;
589c0e09200SDave Airlie 
compat_drm_dma(struct file * file,unsigned int cmd,unsigned long arg)590c0e09200SDave Airlie static int compat_drm_dma(struct file *file, unsigned int cmd,
591c0e09200SDave Airlie 			  unsigned long arg)
592c0e09200SDave Airlie {
593c0e09200SDave Airlie 	drm_dma32_t d32;
594c0e09200SDave Airlie 	drm_dma32_t __user *argp = (void __user *)arg;
595c6f08966SAl Viro 	struct drm_dma d;
596c0e09200SDave Airlie 	int err;
597c0e09200SDave Airlie 
598c0e09200SDave Airlie 	if (copy_from_user(&d32, argp, sizeof(d32)))
599c0e09200SDave Airlie 		return -EFAULT;
600c0e09200SDave Airlie 
601c6f08966SAl Viro 	d.context = d32.context;
602c6f08966SAl Viro 	d.send_count = d32.send_count;
603c6f08966SAl Viro 	d.send_indices = compat_ptr(d32.send_indices);
604c6f08966SAl Viro 	d.send_sizes = compat_ptr(d32.send_sizes);
605c6f08966SAl Viro 	d.flags = d32.flags;
606c6f08966SAl Viro 	d.request_count = d32.request_count;
607c6f08966SAl Viro 	d.request_indices = compat_ptr(d32.request_indices);
608c6f08966SAl Viro 	d.request_sizes = compat_ptr(d32.request_sizes);
609c6f08966SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH);
610c0e09200SDave Airlie 	if (err)
611c0e09200SDave Airlie 		return err;
612c0e09200SDave Airlie 
613c6f08966SAl Viro 	if (put_user(d.request_size, &argp->request_size)
614c6f08966SAl Viro 	    || put_user(d.granted_count, &argp->granted_count))
615c0e09200SDave Airlie 		return -EFAULT;
616c0e09200SDave Airlie 
617c0e09200SDave Airlie 	return 0;
618c0e09200SDave Airlie }
61961ae2270SDave Airlie #endif
620c0e09200SDave Airlie 
62104dfe19aSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_LEGACY)
622a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
623c0e09200SDave Airlie typedef struct drm_agp_mode32 {
624c0e09200SDave Airlie 	u32 mode;	/**< AGP mode */
625c0e09200SDave Airlie } drm_agp_mode32_t;
626c0e09200SDave Airlie 
compat_drm_agp_enable(struct file * file,unsigned int cmd,unsigned long arg)627c0e09200SDave Airlie static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
628c0e09200SDave Airlie 				 unsigned long arg)
629c0e09200SDave Airlie {
630c0e09200SDave Airlie 	drm_agp_mode32_t __user *argp = (void __user *)arg;
631e92673edSAl Viro 	struct drm_agp_mode mode;
632c0e09200SDave Airlie 
633e92673edSAl Viro 	if (get_user(mode.mode, &argp->mode))
634c0e09200SDave Airlie 		return -EFAULT;
635c0e09200SDave Airlie 
63604dfe19aSThomas Zimmermann 	return drm_ioctl_kernel(file,  drm_legacy_agp_enable_ioctl, &mode,
637e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
638c0e09200SDave Airlie }
639c0e09200SDave Airlie 
640c0e09200SDave Airlie typedef struct drm_agp_info32 {
641c0e09200SDave Airlie 	int agp_version_major;
642c0e09200SDave Airlie 	int agp_version_minor;
643c0e09200SDave Airlie 	u32 mode;
644c0e09200SDave Airlie 	u32 aperture_base;	/* physical address */
645c0e09200SDave Airlie 	u32 aperture_size;	/* bytes */
646c0e09200SDave Airlie 	u32 memory_allowed;	/* bytes */
647c0e09200SDave Airlie 	u32 memory_used;
648c0e09200SDave Airlie 
649c0e09200SDave Airlie 	/* PCI information */
650c0e09200SDave Airlie 	unsigned short id_vendor;
651c0e09200SDave Airlie 	unsigned short id_device;
652c0e09200SDave Airlie } drm_agp_info32_t;
653c0e09200SDave Airlie 
compat_drm_agp_info(struct file * file,unsigned int cmd,unsigned long arg)654c0e09200SDave Airlie static int compat_drm_agp_info(struct file *file, unsigned int cmd,
655c0e09200SDave Airlie 			       unsigned long arg)
656c0e09200SDave Airlie {
657c0e09200SDave Airlie 	drm_agp_info32_t __user *argp = (void __user *)arg;
658c0e09200SDave Airlie 	drm_agp_info32_t i32;
659e92673edSAl Viro 	struct drm_agp_info info;
660c0e09200SDave Airlie 	int err;
661c0e09200SDave Airlie 
66204dfe19aSThomas Zimmermann 	err = drm_ioctl_kernel(file, drm_legacy_agp_info_ioctl, &info, DRM_AUTH);
663c0e09200SDave Airlie 	if (err)
664c0e09200SDave Airlie 		return err;
665c0e09200SDave Airlie 
666e92673edSAl Viro 	i32.agp_version_major = info.agp_version_major;
667e92673edSAl Viro 	i32.agp_version_minor = info.agp_version_minor;
668e92673edSAl Viro 	i32.mode = info.mode;
669e92673edSAl Viro 	i32.aperture_base = info.aperture_base;
670e92673edSAl Viro 	i32.aperture_size = info.aperture_size;
671e92673edSAl Viro 	i32.memory_allowed = info.memory_allowed;
672e92673edSAl Viro 	i32.memory_used = info.memory_used;
673e92673edSAl Viro 	i32.id_vendor = info.id_vendor;
674e92673edSAl Viro 	i32.id_device = info.id_device;
675c0e09200SDave Airlie 	if (copy_to_user(argp, &i32, sizeof(i32)))
676c0e09200SDave Airlie 		return -EFAULT;
677c0e09200SDave Airlie 
678c0e09200SDave Airlie 	return 0;
679c0e09200SDave Airlie }
680c0e09200SDave Airlie 
681c0e09200SDave Airlie typedef struct drm_agp_buffer32 {
682c0e09200SDave Airlie 	u32 size;	/**< In bytes -- will round to page boundary */
683c0e09200SDave Airlie 	u32 handle;	/**< Used for binding / unbinding */
684c0e09200SDave Airlie 	u32 type;	/**< Type of memory to allocate */
685c0e09200SDave Airlie 	u32 physical;	/**< Physical used by i810 */
686c0e09200SDave Airlie } drm_agp_buffer32_t;
687c0e09200SDave Airlie 
compat_drm_agp_alloc(struct file * file,unsigned int cmd,unsigned long arg)688c0e09200SDave Airlie static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
689c0e09200SDave Airlie 				unsigned long arg)
690c0e09200SDave Airlie {
691c0e09200SDave Airlie 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
692c0e09200SDave Airlie 	drm_agp_buffer32_t req32;
693e92673edSAl Viro 	struct drm_agp_buffer request;
694c0e09200SDave Airlie 	int err;
695c0e09200SDave Airlie 
696c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
697c0e09200SDave Airlie 		return -EFAULT;
698c0e09200SDave Airlie 
699e92673edSAl Viro 	request.size = req32.size;
700e92673edSAl Viro 	request.type = req32.type;
70104dfe19aSThomas Zimmermann 	err = drm_ioctl_kernel(file, drm_legacy_agp_alloc_ioctl, &request,
702e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
703c0e09200SDave Airlie 	if (err)
704c0e09200SDave Airlie 		return err;
705c0e09200SDave Airlie 
706e92673edSAl Viro 	req32.handle = request.handle;
707e92673edSAl Viro 	req32.physical = request.physical;
708e92673edSAl Viro 	if (copy_to_user(argp, &req32, sizeof(req32))) {
70904dfe19aSThomas Zimmermann 		drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
710e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
711c0e09200SDave Airlie 		return -EFAULT;
712c0e09200SDave Airlie 	}
713c0e09200SDave Airlie 
714c0e09200SDave Airlie 	return 0;
715c0e09200SDave Airlie }
716c0e09200SDave Airlie 
compat_drm_agp_free(struct file * file,unsigned int cmd,unsigned long arg)717c0e09200SDave Airlie static int compat_drm_agp_free(struct file *file, unsigned int cmd,
718c0e09200SDave Airlie 			       unsigned long arg)
719c0e09200SDave Airlie {
720c0e09200SDave Airlie 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
721e92673edSAl Viro 	struct drm_agp_buffer request;
722c0e09200SDave Airlie 
723e92673edSAl Viro 	if (get_user(request.handle, &argp->handle))
724c0e09200SDave Airlie 		return -EFAULT;
725c0e09200SDave Airlie 
72604dfe19aSThomas Zimmermann 	return drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
727e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
728c0e09200SDave Airlie }
729c0e09200SDave Airlie 
730c0e09200SDave Airlie typedef struct drm_agp_binding32 {
731c0e09200SDave Airlie 	u32 handle;	/**< From drm_agp_buffer */
732c0e09200SDave Airlie 	u32 offset;	/**< In bytes -- will round to page boundary */
733c0e09200SDave Airlie } drm_agp_binding32_t;
734c0e09200SDave Airlie 
compat_drm_agp_bind(struct file * file,unsigned int cmd,unsigned long arg)735c0e09200SDave Airlie static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
736c0e09200SDave Airlie 			       unsigned long arg)
737c0e09200SDave Airlie {
738c0e09200SDave Airlie 	drm_agp_binding32_t __user *argp = (void __user *)arg;
739c0e09200SDave Airlie 	drm_agp_binding32_t req32;
740e92673edSAl Viro 	struct drm_agp_binding request;
741c0e09200SDave Airlie 
742c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
743c0e09200SDave Airlie 		return -EFAULT;
744c0e09200SDave Airlie 
745e92673edSAl Viro 	request.handle = req32.handle;
746e92673edSAl Viro 	request.offset = req32.offset;
74704dfe19aSThomas Zimmermann 	return drm_ioctl_kernel(file, drm_legacy_agp_bind_ioctl, &request,
748e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
749c0e09200SDave Airlie }
750c0e09200SDave Airlie 
compat_drm_agp_unbind(struct file * file,unsigned int cmd,unsigned long arg)751c0e09200SDave Airlie static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
752c0e09200SDave Airlie 				 unsigned long arg)
753c0e09200SDave Airlie {
754c0e09200SDave Airlie 	drm_agp_binding32_t __user *argp = (void __user *)arg;
755e92673edSAl Viro 	struct drm_agp_binding request;
756c0e09200SDave Airlie 
757e92673edSAl Viro 	if (get_user(request.handle, &argp->handle))
758c0e09200SDave Airlie 		return -EFAULT;
759c0e09200SDave Airlie 
76004dfe19aSThomas Zimmermann 	return drm_ioctl_kernel(file, drm_legacy_agp_unbind_ioctl, &request,
761e92673edSAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
762c0e09200SDave Airlie }
763a7fb8a23SDaniel Vetter #endif /* CONFIG_AGP */
764c0e09200SDave Airlie 
765c0e09200SDave Airlie typedef struct drm_scatter_gather32 {
766c0e09200SDave Airlie 	u32 size;	/**< In bytes -- will round to page boundary */
767c0e09200SDave Airlie 	u32 handle;	/**< Used for mapping / unmapping */
768c0e09200SDave Airlie } drm_scatter_gather32_t;
769c0e09200SDave Airlie 
compat_drm_sg_alloc(struct file * file,unsigned int cmd,unsigned long arg)770c0e09200SDave Airlie static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
771c0e09200SDave Airlie 			       unsigned long arg)
772c0e09200SDave Airlie {
773c0e09200SDave Airlie 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
774314ed736SAl Viro 	struct drm_scatter_gather request;
775c0e09200SDave Airlie 	int err;
776c0e09200SDave Airlie 
777314ed736SAl Viro 	if (get_user(request.size, &argp->size))
778c0e09200SDave Airlie 		return -EFAULT;
779c0e09200SDave Airlie 
780314ed736SAl Viro 	err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request,
781314ed736SAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
782c0e09200SDave Airlie 	if (err)
783c0e09200SDave Airlie 		return err;
784c0e09200SDave Airlie 
785c0e09200SDave Airlie 	/* XXX not sure about the handle conversion here... */
786314ed736SAl Viro 	if (put_user(request.handle >> PAGE_SHIFT, &argp->handle))
787c0e09200SDave Airlie 		return -EFAULT;
788c0e09200SDave Airlie 
789c0e09200SDave Airlie 	return 0;
790c0e09200SDave Airlie }
791c0e09200SDave Airlie 
compat_drm_sg_free(struct file * file,unsigned int cmd,unsigned long arg)792c0e09200SDave Airlie static int compat_drm_sg_free(struct file *file, unsigned int cmd,
793c0e09200SDave Airlie 			      unsigned long arg)
794c0e09200SDave Airlie {
795c0e09200SDave Airlie 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
796314ed736SAl Viro 	struct drm_scatter_gather request;
797c0e09200SDave Airlie 	unsigned long x;
798c0e09200SDave Airlie 
799314ed736SAl Viro 	if (get_user(x, &argp->handle))
800c0e09200SDave Airlie 		return -EFAULT;
801314ed736SAl Viro 	request.handle = x << PAGE_SHIFT;
802314ed736SAl Viro 	return drm_ioctl_kernel(file, drm_legacy_sg_free, &request,
803314ed736SAl Viro 				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
804c0e09200SDave Airlie }
80561ae2270SDave Airlie #endif
8069cc73ce2SAl Viro #if defined(CONFIG_X86)
80749568873SEric Anholt typedef struct drm_update_draw32 {
80849568873SEric Anholt 	drm_drawable_t handle;
80949568873SEric Anholt 	unsigned int type;
81049568873SEric Anholt 	unsigned int num;
81149568873SEric Anholt 	/* 64-bit version has a 32-bit pad here */
81249568873SEric Anholt 	u64 data;	/**< Pointer */
81349568873SEric Anholt } __attribute__((packed)) drm_update_draw32_t;
81449568873SEric Anholt 
compat_drm_update_draw(struct file * file,unsigned int cmd,unsigned long arg)81549568873SEric Anholt static int compat_drm_update_draw(struct file *file, unsigned int cmd,
81649568873SEric Anholt 				  unsigned long arg)
81749568873SEric Anholt {
8182da9a1a2SDaniel Vetter 	/* update_draw is defunct */
8192da9a1a2SDaniel Vetter 	return 0;
82049568873SEric Anholt }
82109e40d65SDavid Miller #endif
82249568873SEric Anholt 
823c0e09200SDave Airlie struct drm_wait_vblank_request32 {
824c0e09200SDave Airlie 	enum drm_vblank_seq_type type;
825c0e09200SDave Airlie 	unsigned int sequence;
826c0e09200SDave Airlie 	u32 signal;
827c0e09200SDave Airlie };
828c0e09200SDave Airlie 
829c0e09200SDave Airlie struct drm_wait_vblank_reply32 {
830c0e09200SDave Airlie 	enum drm_vblank_seq_type type;
831c0e09200SDave Airlie 	unsigned int sequence;
832c0e09200SDave Airlie 	s32 tval_sec;
833c0e09200SDave Airlie 	s32 tval_usec;
834c0e09200SDave Airlie };
835c0e09200SDave Airlie 
836c0e09200SDave Airlie typedef union drm_wait_vblank32 {
837c0e09200SDave Airlie 	struct drm_wait_vblank_request32 request;
838c0e09200SDave Airlie 	struct drm_wait_vblank_reply32 reply;
839c0e09200SDave Airlie } drm_wait_vblank32_t;
840c0e09200SDave Airlie 
compat_drm_wait_vblank(struct file * file,unsigned int cmd,unsigned long arg)841c0e09200SDave Airlie static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
842c0e09200SDave Airlie 				  unsigned long arg)
843c0e09200SDave Airlie {
844c0e09200SDave Airlie 	drm_wait_vblank32_t __user *argp = (void __user *)arg;
845c0e09200SDave Airlie 	drm_wait_vblank32_t req32;
846d5288c88SAl Viro 	union drm_wait_vblank req;
847c0e09200SDave Airlie 	int err;
848c0e09200SDave Airlie 
849c0e09200SDave Airlie 	if (copy_from_user(&req32, argp, sizeof(req32)))
850c0e09200SDave Airlie 		return -EFAULT;
851c0e09200SDave Airlie 
852e926c474SDaniel Vetter 	memset(&req, 0, sizeof(req));
853e926c474SDaniel Vetter 
854d5288c88SAl Viro 	req.request.type = req32.request.type;
855d5288c88SAl Viro 	req.request.sequence = req32.request.sequence;
856d5288c88SAl Viro 	req.request.signal = req32.request.signal;
857af055598SDaniel Vetter 	err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
858c0e09200SDave Airlie 
859d5288c88SAl Viro 	req32.reply.type = req.reply.type;
860d5288c88SAl Viro 	req32.reply.sequence = req.reply.sequence;
861d5288c88SAl Viro 	req32.reply.tval_sec = req.reply.tval_sec;
862d5288c88SAl Viro 	req32.reply.tval_usec = req.reply.tval_usec;
863c0e09200SDave Airlie 	if (copy_to_user(argp, &req32, sizeof(req32)))
864c0e09200SDave Airlie 		return -EFAULT;
865c0e09200SDave Airlie 
866fa0b1ef5SMark Yacoub 	return err;
867c0e09200SDave Airlie }
868c0e09200SDave Airlie 
8699cc73ce2SAl Viro #if defined(CONFIG_X86)
870c631d5f9STvrtko Ursulin typedef struct drm_mode_fb_cmd232 {
871c631d5f9STvrtko Ursulin 	u32 fb_id;
872c631d5f9STvrtko Ursulin 	u32 width;
873c631d5f9STvrtko Ursulin 	u32 height;
874c631d5f9STvrtko Ursulin 	u32 pixel_format;
875c631d5f9STvrtko Ursulin 	u32 flags;
876c631d5f9STvrtko Ursulin 	u32 handles[4];
877c631d5f9STvrtko Ursulin 	u32 pitches[4];
878c631d5f9STvrtko Ursulin 	u32 offsets[4];
879c631d5f9STvrtko Ursulin 	u64 modifier[4];
880c631d5f9STvrtko Ursulin } __attribute__((packed)) drm_mode_fb_cmd232_t;
881c631d5f9STvrtko Ursulin 
compat_drm_mode_addfb2(struct file * file,unsigned int cmd,unsigned long arg)882c631d5f9STvrtko Ursulin static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
883c631d5f9STvrtko Ursulin 				  unsigned long arg)
884c631d5f9STvrtko Ursulin {
885c631d5f9STvrtko Ursulin 	struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg;
886b87b786bSAl Viro 	struct drm_mode_fb_cmd2 req64;
887c631d5f9STvrtko Ursulin 	int err;
888c631d5f9STvrtko Ursulin 
889e926c474SDaniel Vetter 	memset(&req64, 0, sizeof(req64));
890e926c474SDaniel Vetter 
891d6c56613SAl Viro 	if (copy_from_user(&req64, argp,
892d6c56613SAl Viro 			   offsetof(drm_mode_fb_cmd232_t, modifier)))
893c631d5f9STvrtko Ursulin 		return -EFAULT;
894c631d5f9STvrtko Ursulin 
895d6c56613SAl Viro 	if (copy_from_user(&req64.modifier, &argp->modifier,
896d6c56613SAl Viro 			   sizeof(req64.modifier)))
897c631d5f9STvrtko Ursulin 		return -EFAULT;
898c631d5f9STvrtko Ursulin 
89975426367SDaniel Vetter 	err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0);
900c631d5f9STvrtko Ursulin 	if (err)
901c631d5f9STvrtko Ursulin 		return err;
902c631d5f9STvrtko Ursulin 
903d6c56613SAl Viro 	if (put_user(req64.fb_id, &argp->fb_id))
904c631d5f9STvrtko Ursulin 		return -EFAULT;
905c631d5f9STvrtko Ursulin 
906c631d5f9STvrtko Ursulin 	return 0;
907c631d5f9STvrtko Ursulin }
908a988588bSKristian H. Kristensen #endif
909c631d5f9STvrtko Ursulin 
9109f43e542SAl Viro static struct {
9119f43e542SAl Viro 	drm_ioctl_compat_t *fn;
9129f43e542SAl Viro 	char *name;
9139f43e542SAl Viro } drm_compat_ioctls[] = {
914ff22ff9eSAl Viro #define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n}
915012c6741SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version),
91617e3dadeSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique),
91761ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
9188c4fe499SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap),
91961ae2270SDave Airlie #endif
9209e92662dSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient),
9218547ee9dSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats),
92256c275ccSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique),
92361ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
924b36180a3SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap),
925ff22ff9eSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs),
926dbae740eSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs),
9275c7640abSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs),
92887d3ce11SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs),
9298c9e4cfbSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs),
9306113252dSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap),
9317900c600SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx),
932d7631e30SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx),
9339e075680SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx),
934c6f08966SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma),
935a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
936e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable),
937e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info),
938e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc),
939e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free),
940e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind),
941e92673edSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind),
942c0e09200SDave Airlie #endif
94304dfe19aSThomas Zimmermann #endif
94461ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
945314ed736SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc),
946314ed736SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free),
94761ae2270SDave Airlie #endif
94809e40d65SDavid Miller #if defined(CONFIG_X86) || defined(CONFIG_IA64)
9491a36bf1dSAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw),
95009e40d65SDavid Miller #endif
951d5288c88SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_WAIT_VBLANK, compat_drm_wait_vblank),
952a988588bSKristian H. Kristensen #if defined(CONFIG_X86) || defined(CONFIG_IA64)
953d6c56613SAl Viro 	DRM_IOCTL32_DEF(DRM_IOCTL_MODE_ADDFB2, compat_drm_mode_addfb2),
954a988588bSKristian H. Kristensen #endif
955c0e09200SDave Airlie };
956c0e09200SDave Airlie 
957c0e09200SDave Airlie /**
9582640981fSDaniel Vetter  * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
9592640981fSDaniel Vetter  * @filp: file this ioctl is called on
9602640981fSDaniel Vetter  * @cmd: ioctl cmd number
9612640981fSDaniel Vetter  * @arg: user argument
962c0e09200SDave Airlie  *
9632640981fSDaniel Vetter  * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
9642640981fSDaniel Vetter  * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
9652640981fSDaniel Vetter  * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
9662640981fSDaniel Vetter  * botched IOCTL itself, it must handle those by wrapping this function.
9672640981fSDaniel Vetter  *
9682640981fSDaniel Vetter  * Returns:
9692640981fSDaniel Vetter  * Zero on success, negative error code on failure.
970c0e09200SDave Airlie  */
drm_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)971c0e09200SDave Airlie long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
972c0e09200SDave Airlie {
973c0e09200SDave Airlie 	unsigned int nr = DRM_IOCTL_NR(cmd);
97488e3cb07SAl Viro 	struct drm_file *file_priv = filp->private_data;
975*723dad97STvrtko Ursulin 	struct drm_device *dev = file_priv->minor->dev;
976c0e09200SDave Airlie 	drm_ioctl_compat_t *fn;
977c0e09200SDave Airlie 	int ret;
978c0e09200SDave Airlie 
979c0e09200SDave Airlie 	/* Assume that ioctls without an explicit compat routine will just
980c0e09200SDave Airlie 	 * work.  This may not always be a good assumption, but it's better
981c0e09200SDave Airlie 	 * than always failing.
982c0e09200SDave Airlie 	 */
983c0e09200SDave Airlie 	if (nr >= ARRAY_SIZE(drm_compat_ioctls))
984ed8b6704SArnd Bergmann 		return drm_ioctl(filp, cmd, arg);
985c0e09200SDave Airlie 
9869f43e542SAl Viro 	fn = drm_compat_ioctls[nr].fn;
9879f43e542SAl Viro 	if (!fn)
9889f43e542SAl Viro 		return drm_ioctl(filp, cmd, arg);
989c0e09200SDave Airlie 
990*723dad97STvrtko Ursulin 	drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
9915a2ba992SEmil Velikov 		     current->comm, task_pid_nr(current),
9929f43e542SAl Viro 		     (long)old_encode_dev(file_priv->minor->kdev->devt),
9939f43e542SAl Viro 		     file_priv->authenticated,
9949f43e542SAl Viro 		     drm_compat_ioctls[nr].name);
995c0e09200SDave Airlie 	ret = (*fn)(filp, cmd, arg);
9969f43e542SAl Viro 	if (ret)
997*723dad97STvrtko Ursulin 		drm_dbg_core(dev, "ret = %d\n", ret);
998c0e09200SDave Airlie 	return ret;
999c0e09200SDave Airlie }
1000c0e09200SDave Airlie EXPORT_SYMBOL(drm_compat_ioctl);
1001