Home | History | Annotate | Line # | Download | only in drm
drm_ioctl.c revision 1.4.18.1
      1  1.4.18.1  christos /*	$NetBSD: drm_ioctl.c,v 1.4.18.1 2019/06/10 22:07:57 christos Exp $	*/
      2       1.1  riastrad 
      3       1.1  riastrad /*
      4       1.1  riastrad  * Created: Fri Jan  8 09:01:26 1999 by faith (at) valinux.com
      5       1.1  riastrad  *
      6       1.1  riastrad  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
      7       1.1  riastrad  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
      8       1.1  riastrad  * All Rights Reserved.
      9       1.1  riastrad  *
     10  1.4.18.1  christos  * Author Rickard E. (Rik) Faith <faith (at) valinux.com>
     11  1.4.18.1  christos  * Author Gareth Hughes <gareth (at) valinux.com>
     12  1.4.18.1  christos  *
     13       1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
     14       1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
     15       1.1  riastrad  * to deal in the Software without restriction, including without limitation
     16       1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     17       1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     18       1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     19       1.1  riastrad  *
     20       1.1  riastrad  * The above copyright notice and this permission notice (including the next
     21       1.1  riastrad  * paragraph) shall be included in all copies or substantial portions of the
     22       1.1  riastrad  * Software.
     23       1.1  riastrad  *
     24       1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     25       1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     26       1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     27       1.1  riastrad  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     28       1.1  riastrad  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     29       1.1  riastrad  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     30       1.1  riastrad  * OTHER DEALINGS IN THE SOFTWARE.
     31       1.1  riastrad  */
     32       1.1  riastrad 
     33  1.4.18.1  christos #include <sys/cdefs.h>
     34  1.4.18.1  christos __KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.4.18.1 2019/06/10 22:07:57 christos Exp $");
     35  1.4.18.1  christos 
     36       1.1  riastrad #include <drm/drmP.h>
     37       1.1  riastrad #include <drm/drm_core.h>
     38  1.4.18.1  christos #include "drm_legacy.h"
     39  1.4.18.1  christos #include "drm_internal.h"
     40  1.4.18.1  christos #include "drm_crtc_internal.h"
     41       1.1  riastrad 
     42       1.1  riastrad #include <linux/pci.h>
     43       1.1  riastrad #include <linux/export.h>
     44       1.1  riastrad 
     45  1.4.18.1  christos static int drm_version(struct drm_device *dev, void *data,
     46  1.4.18.1  christos 		       struct drm_file *file_priv);
     47  1.4.18.1  christos 
     48  1.4.18.1  christos /*
     49       1.1  riastrad  * Get the bus id.
     50       1.1  riastrad  *
     51       1.1  riastrad  * \param inode device inode.
     52       1.1  riastrad  * \param file_priv DRM file private.
     53       1.1  riastrad  * \param cmd command.
     54       1.1  riastrad  * \param arg user argument, pointing to a drm_unique structure.
     55       1.1  riastrad  * \return zero on success or a negative number on failure.
     56       1.1  riastrad  *
     57       1.1  riastrad  * Copies the bus id from drm_device::unique into user space.
     58       1.1  riastrad  */
     59  1.4.18.1  christos static int drm_getunique(struct drm_device *dev, void *data,
     60       1.1  riastrad 		  struct drm_file *file_priv)
     61       1.1  riastrad {
     62       1.1  riastrad 	struct drm_unique *u = data;
     63       1.1  riastrad 	struct drm_master *master = file_priv->master;
     64       1.1  riastrad 
     65       1.1  riastrad 	if (u->unique_len >= master->unique_len) {
     66       1.1  riastrad 		if (copy_to_user(u->unique, master->unique, master->unique_len))
     67       1.1  riastrad 			return -EFAULT;
     68       1.1  riastrad 	}
     69       1.1  riastrad 	u->unique_len = master->unique_len;
     70       1.1  riastrad 
     71       1.1  riastrad 	return 0;
     72       1.1  riastrad }
     73       1.1  riastrad 
     74       1.1  riastrad static void
     75       1.1  riastrad drm_unset_busid(struct drm_device *dev,
     76       1.1  riastrad 		struct drm_master *master)
     77       1.1  riastrad {
     78       1.1  riastrad 	kfree(master->unique);
     79       1.1  riastrad 	master->unique = NULL;
     80       1.1  riastrad 	master->unique_len = 0;
     81       1.1  riastrad }
     82       1.1  riastrad 
     83  1.4.18.1  christos /*
     84       1.1  riastrad  * Set the bus id.
     85       1.1  riastrad  *
     86       1.1  riastrad  * \param inode device inode.
     87       1.1  riastrad  * \param file_priv DRM file private.
     88       1.1  riastrad  * \param cmd command.
     89       1.1  riastrad  * \param arg user argument, pointing to a drm_unique structure.
     90       1.1  riastrad  * \return zero on success or a negative number on failure.
     91       1.1  riastrad  *
     92       1.1  riastrad  * Copies the bus id from userspace into drm_device::unique, and verifies that
     93       1.1  riastrad  * it matches the device this DRM is attached to (EINVAL otherwise).  Deprecated
     94       1.1  riastrad  * in interface version 1.1 and will return EBUSY when setversion has requested
     95  1.4.18.1  christos  * version 1.1 or greater. Also note that KMS is all version 1.1 and later and
     96  1.4.18.1  christos  * UMS was only ever supported on pci devices.
     97       1.1  riastrad  */
     98  1.4.18.1  christos static int drm_setunique(struct drm_device *dev, void *data,
     99       1.1  riastrad 		  struct drm_file *file_priv)
    100       1.1  riastrad {
    101       1.1  riastrad 	struct drm_unique *u = data;
    102       1.1  riastrad 	struct drm_master *master = file_priv->master;
    103       1.1  riastrad 	int ret;
    104       1.1  riastrad 
    105       1.1  riastrad 	if (master->unique_len || master->unique)
    106       1.1  riastrad 		return -EBUSY;
    107       1.1  riastrad 
    108       1.1  riastrad 	if (!u->unique_len || u->unique_len > 1024)
    109       1.1  riastrad 		return -EINVAL;
    110       1.1  riastrad 
    111  1.4.18.1  christos 	if (drm_core_check_feature(dev, DRIVER_MODESET))
    112  1.4.18.1  christos 		return 0;
    113  1.4.18.1  christos 
    114  1.4.18.1  christos 	if (WARN_ON(!dev->pdev))
    115       1.1  riastrad 		return -EINVAL;
    116       1.1  riastrad 
    117  1.4.18.1  christos 	if (!dev->driver->set_unique)
    118  1.4.18.1  christos 		return -ENODEV;
    119  1.4.18.1  christos 
    120  1.4.18.1  christos 	ret = dev->driver->set_unique(dev, master, u);
    121       1.1  riastrad 	if (ret)
    122       1.1  riastrad 		goto err;
    123       1.1  riastrad 
    124       1.1  riastrad 	return 0;
    125       1.1  riastrad 
    126       1.1  riastrad err:
    127       1.1  riastrad 	drm_unset_busid(dev, master);
    128       1.1  riastrad 	return ret;
    129       1.1  riastrad }
    130       1.1  riastrad 
    131       1.1  riastrad static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
    132       1.1  riastrad {
    133       1.1  riastrad 	struct drm_master *master = file_priv->master;
    134       1.1  riastrad 	int ret;
    135       1.1  riastrad 
    136       1.1  riastrad 	if (master->unique != NULL)
    137       1.1  riastrad 		drm_unset_busid(dev, master);
    138       1.1  riastrad 
    139  1.4.18.1  christos 	if (dev->driver->set_busid) {
    140  1.4.18.1  christos 		ret = dev->driver->set_busid(dev, master);
    141  1.4.18.1  christos 		if (ret) {
    142  1.4.18.1  christos 			drm_unset_busid(dev, master);
    143  1.4.18.1  christos 			return ret;
    144  1.4.18.1  christos 		}
    145  1.4.18.1  christos 	} else {
    146  1.4.18.1  christos 		if (WARN(dev->unique == NULL,
    147  1.4.18.1  christos 			 "No drm_driver.set_busid() implementation provided by "
    148  1.4.18.1  christos 			 "%ps. Use drm_dev_set_unique() to set the unique "
    149  1.4.18.1  christos 			 "name explicitly.", dev->driver))
    150  1.4.18.1  christos 			return -EINVAL;
    151  1.4.18.1  christos 
    152  1.4.18.1  christos 		master->unique = kstrdup(dev->unique, GFP_KERNEL);
    153  1.4.18.1  christos 		if (master->unique)
    154  1.4.18.1  christos 			master->unique_len = strlen(dev->unique);
    155  1.4.18.1  christos 	}
    156  1.4.18.1  christos 
    157       1.1  riastrad 	return 0;
    158       1.1  riastrad }
    159       1.1  riastrad 
    160  1.4.18.1  christos /*
    161       1.1  riastrad  * Get a mapping information.
    162       1.1  riastrad  *
    163       1.1  riastrad  * \param inode device inode.
    164       1.1  riastrad  * \param file_priv DRM file private.
    165       1.1  riastrad  * \param cmd command.
    166       1.1  riastrad  * \param arg user argument, pointing to a drm_map structure.
    167       1.1  riastrad  *
    168       1.1  riastrad  * \return zero on success or a negative number on failure.
    169       1.1  riastrad  *
    170       1.1  riastrad  * Searches for the mapping with the specified offset and copies its information
    171       1.1  riastrad  * into userspace
    172       1.1  riastrad  */
    173  1.4.18.1  christos static int drm_getmap(struct drm_device *dev, void *data,
    174       1.1  riastrad 	       struct drm_file *file_priv)
    175       1.1  riastrad {
    176       1.1  riastrad 	struct drm_map *map = data;
    177       1.1  riastrad 	struct drm_map_list *r_list = NULL;
    178       1.1  riastrad 	struct list_head *list;
    179       1.1  riastrad 	int idx;
    180       1.1  riastrad 	int i;
    181       1.1  riastrad 
    182       1.1  riastrad 	idx = map->offset;
    183       1.1  riastrad 	if (idx < 0)
    184       1.1  riastrad 		return -EINVAL;
    185       1.1  riastrad 
    186       1.1  riastrad 	i = 0;
    187       1.1  riastrad 	mutex_lock(&dev->struct_mutex);
    188       1.1  riastrad 	list_for_each(list, &dev->maplist) {
    189       1.1  riastrad 		if (i == idx) {
    190       1.1  riastrad 			r_list = list_entry(list, struct drm_map_list, head);
    191       1.1  riastrad 			break;
    192       1.1  riastrad 		}
    193       1.1  riastrad 		i++;
    194       1.1  riastrad 	}
    195       1.1  riastrad 	if (!r_list || !r_list->map) {
    196       1.1  riastrad 		mutex_unlock(&dev->struct_mutex);
    197       1.1  riastrad 		return -EINVAL;
    198       1.1  riastrad 	}
    199       1.1  riastrad 
    200       1.1  riastrad 	map->offset = r_list->map->offset;
    201       1.1  riastrad 	map->size = r_list->map->size;
    202       1.1  riastrad 	map->type = r_list->map->type;
    203       1.1  riastrad 	map->flags = r_list->map->flags;
    204       1.1  riastrad 	map->handle = (void *)(unsigned long) r_list->user_token;
    205  1.4.18.1  christos 	map->mtrr = arch_phys_wc_index(r_list->map->mtrr);
    206       1.3  riastrad 
    207       1.1  riastrad 	mutex_unlock(&dev->struct_mutex);
    208       1.1  riastrad 
    209       1.1  riastrad 	return 0;
    210       1.1  riastrad }
    211       1.1  riastrad 
    212  1.4.18.1  christos /*
    213       1.1  riastrad  * Get client information.
    214       1.1  riastrad  *
    215       1.1  riastrad  * \param inode device inode.
    216       1.1  riastrad  * \param file_priv DRM file private.
    217       1.1  riastrad  * \param cmd command.
    218       1.1  riastrad  * \param arg user argument, pointing to a drm_client structure.
    219       1.1  riastrad  *
    220       1.1  riastrad  * \return zero on success or a negative number on failure.
    221       1.1  riastrad  *
    222       1.1  riastrad  * Searches for the client with the specified index and copies its information
    223       1.1  riastrad  * into userspace
    224       1.1  riastrad  */
    225  1.4.18.1  christos static int drm_getclient(struct drm_device *dev, void *data,
    226       1.1  riastrad 		  struct drm_file *file_priv)
    227       1.1  riastrad {
    228       1.1  riastrad 	struct drm_client *client = data;
    229       1.1  riastrad 
    230       1.3  riastrad 	/*
    231       1.3  riastrad 	 * Hollowed-out getclient ioctl to keep some dead old drm tests/tools
    232       1.3  riastrad 	 * not breaking completely. Userspace tools stop enumerating one they
    233       1.3  riastrad 	 * get -EINVAL, hence this is the return value we need to hand back for
    234       1.3  riastrad 	 * no clients tracked.
    235       1.3  riastrad 	 *
    236       1.3  riastrad 	 * Unfortunately some clients (*cough* libva *cough*) use this in a fun
    237       1.3  riastrad 	 * attempt to figure out whether they're authenticated or not. Since
    238       1.3  riastrad 	 * that's the only thing they care about, give it to the directly
    239       1.3  riastrad 	 * instead of walking one giant list.
    240       1.3  riastrad 	 */
    241       1.3  riastrad 	if (client->idx == 0) {
    242       1.3  riastrad 		client->auth = file_priv->authenticated;
    243       1.2  riastrad #ifdef __NetBSD__		/* XXX Too scary to contemplate.  */
    244       1.4  riastrad 		client->pid = curproc->p_pid;
    245       1.4  riastrad 		client->uid = kauth_cred_geteuid(curproc->p_cred);
    246       1.2  riastrad #else
    247       1.3  riastrad 		client->pid = pid_vnr(file_priv->pid);
    248       1.3  riastrad 		client->uid = from_kuid_munged(current_user_ns(),
    249       1.3  riastrad 					       file_priv->uid);
    250       1.2  riastrad #endif
    251       1.3  riastrad 		client->magic = 0;
    252       1.3  riastrad 		client->iocs = 0;
    253       1.1  riastrad 
    254       1.3  riastrad 		return 0;
    255       1.3  riastrad 	} else {
    256       1.3  riastrad 		return -EINVAL;
    257       1.1  riastrad 	}
    258       1.1  riastrad }
    259       1.1  riastrad 
    260  1.4.18.1  christos /*
    261       1.1  riastrad  * Get statistics information.
    262       1.1  riastrad  *
    263       1.1  riastrad  * \param inode device inode.
    264       1.1  riastrad  * \param file_priv DRM file private.
    265       1.1  riastrad  * \param cmd command.
    266       1.1  riastrad  * \param arg user argument, pointing to a drm_stats structure.
    267       1.1  riastrad  *
    268       1.1  riastrad  * \return zero on success or a negative number on failure.
    269       1.1  riastrad  */
    270  1.4.18.1  christos static int drm_getstats(struct drm_device *dev, void *data,
    271       1.1  riastrad 		 struct drm_file *file_priv)
    272       1.1  riastrad {
    273       1.1  riastrad 	struct drm_stats *stats = data;
    274       1.1  riastrad 
    275       1.3  riastrad 	/* Clear stats to prevent userspace from eating its stack garbage. */
    276       1.1  riastrad 	memset(stats, 0, sizeof(*stats));
    277       1.1  riastrad 
    278       1.1  riastrad 	return 0;
    279       1.1  riastrad }
    280       1.1  riastrad 
    281  1.4.18.1  christos /*
    282       1.1  riastrad  * Get device/driver capabilities
    283       1.1  riastrad  */
    284  1.4.18.1  christos static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
    285       1.1  riastrad {
    286       1.1  riastrad 	struct drm_get_cap *req = data;
    287       1.1  riastrad 
    288       1.1  riastrad 	req->value = 0;
    289       1.1  riastrad 	switch (req->capability) {
    290       1.1  riastrad 	case DRM_CAP_DUMB_BUFFER:
    291       1.1  riastrad 		if (dev->driver->dumb_create)
    292       1.1  riastrad 			req->value = 1;
    293       1.1  riastrad 		break;
    294       1.1  riastrad 	case DRM_CAP_VBLANK_HIGH_CRTC:
    295       1.1  riastrad 		req->value = 1;
    296       1.1  riastrad 		break;
    297       1.1  riastrad 	case DRM_CAP_DUMB_PREFERRED_DEPTH:
    298       1.1  riastrad 		req->value = dev->mode_config.preferred_depth;
    299       1.1  riastrad 		break;
    300       1.1  riastrad 	case DRM_CAP_DUMB_PREFER_SHADOW:
    301       1.1  riastrad 		req->value = dev->mode_config.prefer_shadow;
    302       1.1  riastrad 		break;
    303       1.1  riastrad 	case DRM_CAP_PRIME:
    304       1.1  riastrad 		req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
    305       1.1  riastrad 		req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
    306       1.1  riastrad 		break;
    307       1.1  riastrad 	case DRM_CAP_TIMESTAMP_MONOTONIC:
    308       1.1  riastrad 		req->value = drm_timestamp_monotonic;
    309       1.1  riastrad 		break;
    310       1.3  riastrad 	case DRM_CAP_ASYNC_PAGE_FLIP:
    311       1.3  riastrad 		req->value = dev->mode_config.async_page_flip;
    312       1.3  riastrad 		break;
    313       1.3  riastrad 	case DRM_CAP_CURSOR_WIDTH:
    314       1.3  riastrad 		if (dev->mode_config.cursor_width)
    315       1.3  riastrad 			req->value = dev->mode_config.cursor_width;
    316       1.3  riastrad 		else
    317       1.3  riastrad 			req->value = 64;
    318       1.3  riastrad 		break;
    319       1.3  riastrad 	case DRM_CAP_CURSOR_HEIGHT:
    320       1.3  riastrad 		if (dev->mode_config.cursor_height)
    321       1.3  riastrad 			req->value = dev->mode_config.cursor_height;
    322       1.3  riastrad 		else
    323       1.3  riastrad 			req->value = 64;
    324       1.3  riastrad 		break;
    325  1.4.18.1  christos 	case DRM_CAP_ADDFB2_MODIFIERS:
    326  1.4.18.1  christos 		req->value = dev->mode_config.allow_fb_modifiers;
    327  1.4.18.1  christos 		break;
    328       1.3  riastrad 	default:
    329       1.3  riastrad 		return -EINVAL;
    330       1.3  riastrad 	}
    331       1.3  riastrad 	return 0;
    332       1.3  riastrad }
    333       1.3  riastrad 
    334  1.4.18.1  christos /*
    335       1.3  riastrad  * Set device/driver capabilities
    336       1.3  riastrad  */
    337  1.4.18.1  christos static int
    338       1.3  riastrad drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
    339       1.3  riastrad {
    340       1.3  riastrad 	struct drm_set_client_cap *req = data;
    341       1.3  riastrad 
    342       1.3  riastrad 	switch (req->capability) {
    343       1.3  riastrad 	case DRM_CLIENT_CAP_STEREO_3D:
    344       1.3  riastrad 		if (req->value > 1)
    345       1.3  riastrad 			return -EINVAL;
    346       1.3  riastrad 		file_priv->stereo_allowed = req->value;
    347       1.3  riastrad 		break;
    348       1.3  riastrad 	case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
    349  1.4.18.1  christos 		if (req->value > 1)
    350  1.4.18.1  christos 			return -EINVAL;
    351  1.4.18.1  christos 		file_priv->universal_planes = req->value;
    352  1.4.18.1  christos 		break;
    353  1.4.18.1  christos 	case DRM_CLIENT_CAP_ATOMIC:
    354  1.4.18.1  christos 		if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
    355       1.3  riastrad 			return -EINVAL;
    356       1.3  riastrad 		if (req->value > 1)
    357       1.3  riastrad 			return -EINVAL;
    358  1.4.18.1  christos 		file_priv->atomic = req->value;
    359       1.3  riastrad 		file_priv->universal_planes = req->value;
    360       1.3  riastrad 		break;
    361       1.1  riastrad 	default:
    362       1.1  riastrad 		return -EINVAL;
    363       1.1  riastrad 	}
    364       1.3  riastrad 
    365       1.1  riastrad 	return 0;
    366       1.1  riastrad }
    367       1.1  riastrad 
    368  1.4.18.1  christos /*
    369       1.1  riastrad  * Setversion ioctl.
    370       1.1  riastrad  *
    371       1.1  riastrad  * \param inode device inode.
    372       1.1  riastrad  * \param file_priv DRM file private.
    373       1.1  riastrad  * \param cmd command.
    374       1.1  riastrad  * \param arg user argument, pointing to a drm_lock structure.
    375       1.1  riastrad  * \return zero on success or negative number on failure.
    376       1.1  riastrad  *
    377       1.1  riastrad  * Sets the requested interface version
    378       1.1  riastrad  */
    379  1.4.18.1  christos static int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
    380       1.1  riastrad {
    381       1.1  riastrad 	struct drm_set_version *sv = data;
    382       1.1  riastrad 	int if_version, retcode = 0;
    383       1.1  riastrad 
    384       1.1  riastrad 	if (sv->drm_di_major != -1) {
    385       1.1  riastrad 		if (sv->drm_di_major != DRM_IF_MAJOR ||
    386       1.1  riastrad 		    sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
    387       1.1  riastrad 			retcode = -EINVAL;
    388       1.1  riastrad 			goto done;
    389       1.1  riastrad 		}
    390       1.1  riastrad 		if_version = DRM_IF_VERSION(sv->drm_di_major,
    391       1.1  riastrad 					    sv->drm_di_minor);
    392       1.1  riastrad 		dev->if_version = max(if_version, dev->if_version);
    393       1.1  riastrad 		if (sv->drm_di_minor >= 1) {
    394       1.1  riastrad 			/*
    395       1.1  riastrad 			 * Version 1.1 includes tying of DRM to specific device
    396       1.1  riastrad 			 * Version 1.4 has proper PCI domain support
    397       1.1  riastrad 			 */
    398       1.1  riastrad 			retcode = drm_set_busid(dev, file_priv);
    399       1.1  riastrad 			if (retcode)
    400       1.1  riastrad 				goto done;
    401       1.1  riastrad 		}
    402       1.1  riastrad 	}
    403       1.1  riastrad 
    404       1.1  riastrad 	if (sv->drm_dd_major != -1) {
    405       1.1  riastrad 		if (sv->drm_dd_major != dev->driver->major ||
    406       1.1  riastrad 		    sv->drm_dd_minor < 0 || sv->drm_dd_minor >
    407       1.1  riastrad 		    dev->driver->minor) {
    408       1.1  riastrad 			retcode = -EINVAL;
    409       1.1  riastrad 			goto done;
    410       1.1  riastrad 		}
    411       1.1  riastrad 	}
    412       1.1  riastrad 
    413       1.1  riastrad done:
    414       1.1  riastrad 	sv->drm_di_major = DRM_IF_MAJOR;
    415       1.1  riastrad 	sv->drm_di_minor = DRM_IF_MINOR;
    416       1.1  riastrad 	sv->drm_dd_major = dev->driver->major;
    417       1.1  riastrad 	sv->drm_dd_minor = dev->driver->minor;
    418       1.1  riastrad 
    419       1.1  riastrad 	return retcode;
    420       1.1  riastrad }
    421       1.1  riastrad 
    422  1.4.18.1  christos /**
    423  1.4.18.1  christos  * drm_noop - DRM no-op ioctl implemntation
    424  1.4.18.1  christos  * @dev: DRM device for the ioctl
    425  1.4.18.1  christos  * @data: data pointer for the ioctl
    426  1.4.18.1  christos  * @file_priv: DRM file for the ioctl call
    427  1.4.18.1  christos  *
    428  1.4.18.1  christos  * This no-op implementation for drm ioctls is useful for deprecated
    429  1.4.18.1  christos  * functionality where we can't return a failure code because existing userspace
    430  1.4.18.1  christos  * checks the result of the ioctl, but doesn't care about the action.
    431  1.4.18.1  christos  *
    432  1.4.18.1  christos  * Always returns successfully with 0.
    433  1.4.18.1  christos  */
    434       1.1  riastrad int drm_noop(struct drm_device *dev, void *data,
    435       1.1  riastrad 	     struct drm_file *file_priv)
    436       1.1  riastrad {
    437       1.1  riastrad 	DRM_DEBUG("\n");
    438       1.1  riastrad 	return 0;
    439       1.1  riastrad }
    440       1.1  riastrad EXPORT_SYMBOL(drm_noop);
    441  1.4.18.1  christos 
    442  1.4.18.1  christos /**
    443  1.4.18.1  christos  * drm_invalid_op - DRM invalid ioctl implemntation
    444  1.4.18.1  christos  * @dev: DRM device for the ioctl
    445  1.4.18.1  christos  * @data: data pointer for the ioctl
    446  1.4.18.1  christos  * @file_priv: DRM file for the ioctl call
    447  1.4.18.1  christos  *
    448  1.4.18.1  christos  * This no-op implementation for drm ioctls is useful for deprecated
    449  1.4.18.1  christos  * functionality where we really don't want to allow userspace to call the ioctl
    450  1.4.18.1  christos  * any more. This is the case for old ums interfaces for drivers that
    451  1.4.18.1  christos  * transitioned to kms gradually and so kept the old legacy tables around. This
    452  1.4.18.1  christos  * only applies to radeon and i915 kms drivers, other drivers shouldn't need to
    453  1.4.18.1  christos  * use this function.
    454  1.4.18.1  christos  *
    455  1.4.18.1  christos  * Always fails with a return value of -EINVAL.
    456  1.4.18.1  christos  */
    457  1.4.18.1  christos int drm_invalid_op(struct drm_device *dev, void *data,
    458  1.4.18.1  christos 		   struct drm_file *file_priv)
    459  1.4.18.1  christos {
    460  1.4.18.1  christos 	return -EINVAL;
    461  1.4.18.1  christos }
    462  1.4.18.1  christos EXPORT_SYMBOL(drm_invalid_op);
    463  1.4.18.1  christos 
    464  1.4.18.1  christos /*
    465  1.4.18.1  christos  * Copy and IOCTL return string to user space
    466  1.4.18.1  christos  */
    467  1.4.18.1  christos static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
    468  1.4.18.1  christos {
    469  1.4.18.1  christos 	int len;
    470  1.4.18.1  christos 
    471  1.4.18.1  christos 	/* don't overflow userbuf */
    472  1.4.18.1  christos 	len = strlen(value);
    473  1.4.18.1  christos 	if (len > *buf_len)
    474  1.4.18.1  christos 		len = *buf_len;
    475  1.4.18.1  christos 
    476  1.4.18.1  christos 	/* let userspace know exact length of driver value (which could be
    477  1.4.18.1  christos 	 * larger than the userspace-supplied buffer) */
    478  1.4.18.1  christos 	*buf_len = strlen(value);
    479  1.4.18.1  christos 
    480  1.4.18.1  christos 	/* finally, try filling in the userbuf */
    481  1.4.18.1  christos 	if (len && buf)
    482  1.4.18.1  christos 		if (copy_to_user(buf, value, len))
    483  1.4.18.1  christos 			return -EFAULT;
    484  1.4.18.1  christos 	return 0;
    485  1.4.18.1  christos }
    486  1.4.18.1  christos 
    487  1.4.18.1  christos /*
    488  1.4.18.1  christos  * Get version information
    489  1.4.18.1  christos  *
    490  1.4.18.1  christos  * \param inode device inode.
    491  1.4.18.1  christos  * \param filp file pointer.
    492  1.4.18.1  christos  * \param cmd command.
    493  1.4.18.1  christos  * \param arg user argument, pointing to a drm_version structure.
    494  1.4.18.1  christos  * \return zero on success or negative number on failure.
    495  1.4.18.1  christos  *
    496  1.4.18.1  christos  * Fills in the version information in \p arg.
    497  1.4.18.1  christos  */
    498  1.4.18.1  christos static int drm_version(struct drm_device *dev, void *data,
    499  1.4.18.1  christos 		       struct drm_file *file_priv)
    500  1.4.18.1  christos {
    501  1.4.18.1  christos 	struct drm_version *version = data;
    502  1.4.18.1  christos 	int err;
    503  1.4.18.1  christos 
    504  1.4.18.1  christos 	version->version_major = dev->driver->major;
    505  1.4.18.1  christos 	version->version_minor = dev->driver->minor;
    506  1.4.18.1  christos 	version->version_patchlevel = dev->driver->patchlevel;
    507  1.4.18.1  christos 	err = drm_copy_field(version->name, &version->name_len,
    508  1.4.18.1  christos 			dev->driver->name);
    509  1.4.18.1  christos 	if (!err)
    510  1.4.18.1  christos 		err = drm_copy_field(version->date, &version->date_len,
    511  1.4.18.1  christos 				dev->driver->date);
    512  1.4.18.1  christos 	if (!err)
    513  1.4.18.1  christos 		err = drm_copy_field(version->desc, &version->desc_len,
    514  1.4.18.1  christos 				dev->driver->desc);
    515  1.4.18.1  christos 
    516  1.4.18.1  christos 	return err;
    517  1.4.18.1  christos }
    518  1.4.18.1  christos 
    519  1.4.18.1  christos /*
    520  1.4.18.1  christos  * drm_ioctl_permit - Check ioctl permissions against caller
    521  1.4.18.1  christos  *
    522  1.4.18.1  christos  * @flags: ioctl permission flags.
    523  1.4.18.1  christos  * @file_priv: Pointer to struct drm_file identifying the caller.
    524  1.4.18.1  christos  *
    525  1.4.18.1  christos  * Checks whether the caller is allowed to run an ioctl with the
    526  1.4.18.1  christos  * indicated permissions. If so, returns zero. Otherwise returns an
    527  1.4.18.1  christos  * error code suitable for ioctl return.
    528  1.4.18.1  christos  */
    529  1.4.18.1  christos int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
    530  1.4.18.1  christos {
    531  1.4.18.1  christos 	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
    532  1.4.18.1  christos #ifdef __NetBSD__
    533  1.4.18.1  christos 	if (unlikely((flags & DRM_ROOT_ONLY) && !DRM_SUSER()))
    534  1.4.18.1  christos #else
    535  1.4.18.1  christos 	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
    536  1.4.18.1  christos #endif
    537  1.4.18.1  christos 		return -EACCES;
    538  1.4.18.1  christos 
    539  1.4.18.1  christos 	/* AUTH is only for authenticated or render client */
    540  1.4.18.1  christos 	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
    541  1.4.18.1  christos 		     !file_priv->authenticated))
    542  1.4.18.1  christos 		return -EACCES;
    543  1.4.18.1  christos 
    544  1.4.18.1  christos 	/* MASTER is only for master or control clients */
    545  1.4.18.1  christos 	if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
    546  1.4.18.1  christos 		     !drm_is_control_client(file_priv)))
    547  1.4.18.1  christos 		return -EACCES;
    548  1.4.18.1  christos 
    549  1.4.18.1  christos 	/* Control clients must be explicitly allowed */
    550  1.4.18.1  christos 	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
    551  1.4.18.1  christos 		     drm_is_control_client(file_priv)))
    552  1.4.18.1  christos 		return -EACCES;
    553  1.4.18.1  christos 
    554  1.4.18.1  christos 	/* Render clients must be explicitly allowed */
    555  1.4.18.1  christos 	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
    556  1.4.18.1  christos 		     drm_is_render_client(file_priv)))
    557  1.4.18.1  christos 		return -EACCES;
    558  1.4.18.1  christos 
    559  1.4.18.1  christos 	return 0;
    560  1.4.18.1  christos }
    561  1.4.18.1  christos EXPORT_SYMBOL(drm_ioctl_permit);
    562  1.4.18.1  christos 
    563  1.4.18.1  christos #define DRM_IOCTL_DEF(ioctl, _func, _flags)	\
    564  1.4.18.1  christos 	[DRM_IOCTL_NR(ioctl)] = {		\
    565  1.4.18.1  christos 		.cmd = ioctl,			\
    566  1.4.18.1  christos 		.func = _func,			\
    567  1.4.18.1  christos 		.flags = _flags,		\
    568  1.4.18.1  christos 		.name = #ioctl			\
    569  1.4.18.1  christos 	}
    570  1.4.18.1  christos 
    571  1.4.18.1  christos /* Ioctl table */
    572  1.4.18.1  christos static const struct drm_ioctl_desc drm_ioctls[] = {
    573  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
    574  1.4.18.1  christos 		      DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW),
    575  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
    576  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
    577  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
    578  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
    579  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
    580  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
    581  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
    582  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
    583  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
    584  1.4.18.1  christos 
    585  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    586  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    587  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    588  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
    589  1.4.18.1  christos 
    590  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    591  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH),
    592  1.4.18.1  christos 
    593  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    594  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH),
    595  1.4.18.1  christos 
    596  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
    597  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
    598  1.4.18.1  christos 
    599  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY),
    600  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    601  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    602  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH),
    603  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    604  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    605  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH),
    606  1.4.18.1  christos 
    607  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    608  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    609  1.4.18.1  christos 
    610  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_legacy_lock, DRM_AUTH),
    611  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_legacy_unlock, DRM_AUTH),
    612  1.4.18.1  christos 
    613  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
    614  1.4.18.1  christos 
    615  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_legacy_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    616  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_legacy_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    617  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_legacy_infobufs, DRM_AUTH),
    618  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_legacy_mapbufs, DRM_AUTH),
    619  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_legacy_freebufs, DRM_AUTH),
    620  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_legacy_dma_ioctl, DRM_AUTH),
    621  1.4.18.1  christos 
    622  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    623  1.4.18.1  christos 
    624  1.4.18.1  christos #if IS_ENABLED(CONFIG_AGP)
    625  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    626  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    627  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    628  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
    629  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    630  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    631  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    632  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    633  1.4.18.1  christos #endif
    634  1.4.18.1  christos 
    635  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    636  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    637  1.4.18.1  christos 
    638  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
    639  1.4.18.1  christos 
    640  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
    641  1.4.18.1  christos 
    642  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
    643  1.4.18.1  christos 
    644  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
    645  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
    646  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
    647  1.4.18.1  christos 
    648  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    649  1.4.18.1  christos 
    650  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
    651  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
    652  1.4.18.1  christos 
    653  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    654  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    655  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    656  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    657  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    658  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    659  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
    660  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
    661  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    662  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    663  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    664  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    665  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    666  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    667  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    668  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    669  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    670  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    671  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    672  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    673  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    674  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    675  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    676  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    677  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    678  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    679  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    680  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    681  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    682  1.4.18.1  christos 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
    683  1.4.18.1  christos };
    684  1.4.18.1  christos 
    685  1.4.18.1  christos #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
    686  1.4.18.1  christos 
    687  1.4.18.1  christos /**
    688  1.4.18.1  christos  * drm_ioctl - ioctl callback implementation for DRM drivers
    689  1.4.18.1  christos  * @filp: file this ioctl is called on
    690  1.4.18.1  christos  * @cmd: ioctl cmd number
    691  1.4.18.1  christos  * @arg: user argument
    692  1.4.18.1  christos  *
    693  1.4.18.1  christos  * Looks up the ioctl function in the ::ioctls table, checking for root
    694  1.4.18.1  christos  * previleges if so required, and dispatches to the respective function.
    695  1.4.18.1  christos  *
    696  1.4.18.1  christos  * Returns:
    697  1.4.18.1  christos  * Zero on success, negative error code on failure.
    698  1.4.18.1  christos  */
    699  1.4.18.1  christos #ifdef __NetBSD__
    700  1.4.18.1  christos #include <sys/file.h>
    701  1.4.18.1  christos int
    702  1.4.18.1  christos drm_ioctl(struct file *fp, unsigned long cmd, void *data)
    703  1.4.18.1  christos {
    704  1.4.18.1  christos 	char stackbuf[128];
    705  1.4.18.1  christos 	char *buf = stackbuf;
    706  1.4.18.1  christos 	void *data0 = data;
    707  1.4.18.1  christos 	struct drm_file *const file = fp->f_data;
    708  1.4.18.1  christos 	const unsigned int nr = DRM_IOCTL_NR(cmd);
    709  1.4.18.1  christos 	int error;
    710  1.4.18.1  christos 
    711  1.4.18.1  christos 	switch (cmd) {
    712  1.4.18.1  christos 	case FIONBIO:
    713  1.4.18.1  christos 	case FIOASYNC:
    714  1.4.18.1  christos 		return 0;
    715  1.4.18.1  christos 	default:
    716  1.4.18.1  christos 		break;
    717  1.4.18.1  christos 	}
    718  1.4.18.1  christos 
    719  1.4.18.1  christos 	if (IOCGROUP(cmd) != DRM_IOCTL_BASE)
    720  1.4.18.1  christos 		return EINVAL;
    721  1.4.18.1  christos 
    722  1.4.18.1  christos 	KASSERT(file != NULL);
    723  1.4.18.1  christos 	KASSERT(file->minor != NULL);
    724  1.4.18.1  christos 	KASSERT(file->minor->dev != NULL);
    725  1.4.18.1  christos 	struct drm_device *const dev = file->minor->dev;
    726  1.4.18.1  christos 	const struct drm_ioctl_desc *ioctl;
    727  1.4.18.1  christos 
    728  1.4.18.1  christos 	if (drm_device_is_unplugged(dev))
    729  1.4.18.1  christos 		return ENXIO;
    730  1.4.18.1  christos 
    731  1.4.18.1  christos 	const bool is_driver_ioctl =
    732  1.4.18.1  christos 	    (DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END);
    733  1.4.18.1  christos 
    734  1.4.18.1  christos 	if (is_driver_ioctl) {
    735  1.4.18.1  christos 		const unsigned int driver_nr = nr - DRM_COMMAND_BASE;
    736  1.4.18.1  christos 		if (driver_nr >= dev->driver->num_ioctls)
    737  1.4.18.1  christos 			return EINVAL;
    738  1.4.18.1  christos 		ioctl = &dev->driver->ioctls[driver_nr];
    739  1.4.18.1  christos 	} else if (nr < __arraycount(drm_ioctls)) {
    740  1.4.18.1  christos 		ioctl = &drm_ioctls[nr];
    741  1.4.18.1  christos 	} else {
    742  1.4.18.1  christos 		ioctl = NULL;
    743  1.4.18.1  christos 	}
    744  1.4.18.1  christos 
    745  1.4.18.1  christos 	if ((ioctl == NULL) || (ioctl->func == NULL))
    746  1.4.18.1  christos 		return EINVAL;
    747  1.4.18.1  christos 
    748  1.4.18.1  christos 	/* XXX errno Linux->NetBSD */
    749  1.4.18.1  christos 	error = -drm_ioctl_permit(ioctl->flags, file);
    750  1.4.18.1  christos 	if (error)
    751  1.4.18.1  christos 		return error;
    752  1.4.18.1  christos 
    753  1.4.18.1  christos 	/* If userland passed in too few bytes, zero-pad them.  */
    754  1.4.18.1  christos 	if (IOCPARM_LEN(cmd) < IOCPARM_LEN(ioctl->cmd)) {
    755  1.4.18.1  christos 		/* 12-bit quantity, according to <sys/ioccom.h> */
    756  1.4.18.1  christos 		KASSERT(IOCPARM_LEN(ioctl->cmd) <= 4096);
    757  1.4.18.1  christos 		if (IOCPARM_LEN(ioctl->cmd) > sizeof stackbuf) {
    758  1.4.18.1  christos 			buf = kmem_alloc(IOCPARM_LEN(ioctl->cmd), KM_NOSLEEP);
    759  1.4.18.1  christos 			if (buf == NULL)
    760  1.4.18.1  christos 				return ENOMEM;
    761  1.4.18.1  christos 		}
    762  1.4.18.1  christos 		memcpy(buf, data, IOCPARM_LEN(cmd));
    763  1.4.18.1  christos 		memset(buf + IOCPARM_LEN(cmd), 0,
    764  1.4.18.1  christos 		    IOCPARM_LEN(ioctl->cmd) - IOCPARM_LEN(cmd));
    765  1.4.18.1  christos 		data0 = buf;
    766  1.4.18.1  christos 	}
    767  1.4.18.1  christos 
    768  1.4.18.1  christos 	if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
    769  1.4.18.1  christos 	    ISSET(ioctl->flags, DRM_UNLOCKED)) {
    770  1.4.18.1  christos 		/* XXX errno Linux->NetBSD */
    771  1.4.18.1  christos 		error = -(*ioctl->func)(dev, data0, file);
    772  1.4.18.1  christos 	} else {
    773  1.4.18.1  christos 		mutex_lock(&drm_global_mutex);
    774  1.4.18.1  christos 		/* XXX errno Linux->NetBSD */
    775  1.4.18.1  christos 		error = -(*ioctl->func)(dev, data0, file);
    776  1.4.18.1  christos 		mutex_unlock(&drm_global_mutex);
    777  1.4.18.1  christos 	}
    778  1.4.18.1  christos 
    779  1.4.18.1  christos 	/* If we used a temporary buffer, copy it back out.  */
    780  1.4.18.1  christos 	if (data != data0)
    781  1.4.18.1  christos 		memcpy(data, data0, IOCPARM_LEN(cmd));
    782  1.4.18.1  christos 
    783  1.4.18.1  christos 	/* If we had to allocate a heap buffer, free it.  */
    784  1.4.18.1  christos 	if (buf != stackbuf)
    785  1.4.18.1  christos 		kmem_free(buf, IOCPARM_LEN(ioctl->cmd));
    786  1.4.18.1  christos 
    787  1.4.18.1  christos 	return error;
    788  1.4.18.1  christos }
    789  1.4.18.1  christos #else
    790  1.4.18.1  christos long drm_ioctl(struct file *filp,
    791  1.4.18.1  christos 	      unsigned int cmd, unsigned long arg)
    792  1.4.18.1  christos {
    793  1.4.18.1  christos 	struct drm_file *file_priv = filp->private_data;
    794  1.4.18.1  christos 	struct drm_device *dev;
    795  1.4.18.1  christos 	const struct drm_ioctl_desc *ioctl = NULL;
    796  1.4.18.1  christos 	drm_ioctl_t *func;
    797  1.4.18.1  christos 	unsigned int nr = DRM_IOCTL_NR(cmd);
    798  1.4.18.1  christos 	int retcode = -EINVAL;
    799  1.4.18.1  christos 	char stack_kdata[128];
    800  1.4.18.1  christos 	char *kdata = NULL;
    801  1.4.18.1  christos 	unsigned int usize, asize, drv_size;
    802  1.4.18.1  christos 	bool is_driver_ioctl;
    803  1.4.18.1  christos 
    804  1.4.18.1  christos 	dev = file_priv->minor->dev;
    805  1.4.18.1  christos 
    806  1.4.18.1  christos 	if (drm_device_is_unplugged(dev))
    807  1.4.18.1  christos 		return -ENODEV;
    808  1.4.18.1  christos 
    809  1.4.18.1  christos 	is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
    810  1.4.18.1  christos 
    811  1.4.18.1  christos 	if (is_driver_ioctl) {
    812  1.4.18.1  christos 		/* driver ioctl */
    813  1.4.18.1  christos 		if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
    814  1.4.18.1  christos 			goto err_i1;
    815  1.4.18.1  christos 		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
    816  1.4.18.1  christos 	} else {
    817  1.4.18.1  christos 		/* core ioctl */
    818  1.4.18.1  christos 		if (nr >= DRM_CORE_IOCTL_COUNT)
    819  1.4.18.1  christos 			goto err_i1;
    820  1.4.18.1  christos 		ioctl = &drm_ioctls[nr];
    821  1.4.18.1  christos 	}
    822  1.4.18.1  christos 
    823  1.4.18.1  christos 	drv_size = _IOC_SIZE(ioctl->cmd);
    824  1.4.18.1  christos 	usize = _IOC_SIZE(cmd);
    825  1.4.18.1  christos 	asize = max(usize, drv_size);
    826  1.4.18.1  christos 	cmd = ioctl->cmd;
    827  1.4.18.1  christos 
    828  1.4.18.1  christos 	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
    829  1.4.18.1  christos 		  task_pid_nr(current),
    830  1.4.18.1  christos 		  (long)old_encode_dev(file_priv->minor->kdev->devt),
    831  1.4.18.1  christos 		  file_priv->authenticated, ioctl->name);
    832  1.4.18.1  christos 
    833  1.4.18.1  christos 	/* Do not trust userspace, use our own definition */
    834  1.4.18.1  christos 	func = ioctl->func;
    835  1.4.18.1  christos 
    836  1.4.18.1  christos 	if (unlikely(!func)) {
    837  1.4.18.1  christos 		DRM_DEBUG("no function\n");
    838  1.4.18.1  christos 		retcode = -EINVAL;
    839  1.4.18.1  christos 		goto err_i1;
    840  1.4.18.1  christos 	}
    841  1.4.18.1  christos 
    842  1.4.18.1  christos 	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
    843  1.4.18.1  christos 	if (unlikely(retcode))
    844  1.4.18.1  christos 		goto err_i1;
    845  1.4.18.1  christos 
    846  1.4.18.1  christos 	if (cmd & (IOC_IN | IOC_OUT)) {
    847  1.4.18.1  christos 		if (asize <= sizeof(stack_kdata)) {
    848  1.4.18.1  christos 			kdata = stack_kdata;
    849  1.4.18.1  christos 		} else {
    850  1.4.18.1  christos 			kdata = kmalloc(asize, GFP_KERNEL);
    851  1.4.18.1  christos 			if (!kdata) {
    852  1.4.18.1  christos 				retcode = -ENOMEM;
    853  1.4.18.1  christos 				goto err_i1;
    854  1.4.18.1  christos 			}
    855  1.4.18.1  christos 		}
    856  1.4.18.1  christos 		if (asize > usize)
    857  1.4.18.1  christos 			memset(kdata + usize, 0, asize - usize);
    858  1.4.18.1  christos 	}
    859  1.4.18.1  christos 
    860  1.4.18.1  christos 	if (cmd & IOC_IN) {
    861  1.4.18.1  christos 		if (copy_from_user(kdata, (void __user *)arg,
    862  1.4.18.1  christos 				   usize) != 0) {
    863  1.4.18.1  christos 			retcode = -EFAULT;
    864  1.4.18.1  christos 			goto err_i1;
    865  1.4.18.1  christos 		}
    866  1.4.18.1  christos 	} else if (cmd & IOC_OUT) {
    867  1.4.18.1  christos 		memset(kdata, 0, usize);
    868  1.4.18.1  christos 	}
    869  1.4.18.1  christos 
    870  1.4.18.1  christos 	/* Enforce sane locking for kms driver ioctls. Core ioctls are
    871  1.4.18.1  christos 	 * too messy still. */
    872  1.4.18.1  christos 	if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
    873  1.4.18.1  christos 	    (ioctl->flags & DRM_UNLOCKED))
    874  1.4.18.1  christos 		retcode = func(dev, kdata, file_priv);
    875  1.4.18.1  christos 	else {
    876  1.4.18.1  christos 		mutex_lock(&drm_global_mutex);
    877  1.4.18.1  christos 		retcode = func(dev, kdata, file_priv);
    878  1.4.18.1  christos 		mutex_unlock(&drm_global_mutex);
    879  1.4.18.1  christos 	}
    880  1.4.18.1  christos 
    881  1.4.18.1  christos 	if (cmd & IOC_OUT) {
    882  1.4.18.1  christos 		if (copy_to_user((void __user *)arg, kdata,
    883  1.4.18.1  christos 				 usize) != 0)
    884  1.4.18.1  christos 			retcode = -EFAULT;
    885  1.4.18.1  christos 	}
    886  1.4.18.1  christos 
    887  1.4.18.1  christos       err_i1:
    888  1.4.18.1  christos 	if (!ioctl)
    889  1.4.18.1  christos 		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
    890  1.4.18.1  christos 			  task_pid_nr(current),
    891  1.4.18.1  christos 			  (long)old_encode_dev(file_priv->minor->kdev->devt),
    892  1.4.18.1  christos 			  file_priv->authenticated, cmd, nr);
    893  1.4.18.1  christos 
    894  1.4.18.1  christos 	if (kdata != stack_kdata)
    895  1.4.18.1  christos 		kfree(kdata);
    896  1.4.18.1  christos 	if (retcode)
    897  1.4.18.1  christos 		DRM_DEBUG("ret = %d\n", retcode);
    898  1.4.18.1  christos 	return retcode;
    899  1.4.18.1  christos }
    900  1.4.18.1  christos #endif
    901  1.4.18.1  christos EXPORT_SYMBOL(drm_ioctl);
    902  1.4.18.1  christos 
    903  1.4.18.1  christos /**
    904  1.4.18.1  christos  * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
    905  1.4.18.1  christos  * @nr: ioctl number
    906  1.4.18.1  christos  * @flags: where to return the ioctl permission flags
    907  1.4.18.1  christos  *
    908  1.4.18.1  christos  * This ioctl is only used by the vmwgfx driver to augment the access checks
    909  1.4.18.1  christos  * done by the drm core and insofar a pretty decent layering violation. This
    910  1.4.18.1  christos  * shouldn't be used by any drivers.
    911  1.4.18.1  christos  *
    912  1.4.18.1  christos  * Returns:
    913  1.4.18.1  christos  * True if the @nr corresponds to a DRM core ioctl numer, false otherwise.
    914  1.4.18.1  christos  */
    915  1.4.18.1  christos bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
    916  1.4.18.1  christos {
    917  1.4.18.1  christos 	if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END)
    918  1.4.18.1  christos 		return false;
    919  1.4.18.1  christos 
    920  1.4.18.1  christos 	if (nr >= DRM_CORE_IOCTL_COUNT)
    921  1.4.18.1  christos 		return false;
    922  1.4.18.1  christos 
    923  1.4.18.1  christos 	*flags = drm_ioctls[nr].flags;
    924  1.4.18.1  christos 	return true;
    925  1.4.18.1  christos }
    926  1.4.18.1  christos EXPORT_SYMBOL(drm_ioctl_flags);
    927