Fri Mar 6 14:02:39 2015 UTC ()
Synchronize permission checks with upstream drm_ioctl_permit.


(riastradh)
diff -r1.13 -r1.14 src/sys/external/bsd/drm2/drm/drm_drv.c

cvs diff -r1.13 -r1.14 src/sys/external/bsd/drm2/drm/Attic/drm_drv.c (switch to unified diff)

--- src/sys/external/bsd/drm2/drm/Attic/drm_drv.c 2015/01/01 01:15:42 1.13
+++ src/sys/external/bsd/drm2/drm/Attic/drm_drv.c 2015/03/06 14:02:39 1.14
@@ -1,816 +1,825 @@ @@ -1,816 +1,825 @@
1/* $NetBSD: drm_drv.c,v 1.13 2015/01/01 01:15:42 mrg Exp $ */ 1/* $NetBSD: drm_drv.c,v 1.14 2015/03/06 14:02:39 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell. 8 * by Taylor R. Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.13 2015/01/01 01:15:42 mrg Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.14 2015/03/06 14:02:39 riastradh Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/types.h> 36#include <sys/types.h>
37#include <sys/conf.h> 37#include <sys/conf.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/file.h> 39#include <sys/file.h>
40#include <sys/filedesc.h> 40#include <sys/filedesc.h>
41#include <sys/ioccom.h> 41#include <sys/ioccom.h>
42#include <sys/kauth.h> 42#include <sys/kauth.h>
43#ifndef _MODULE 43#ifndef _MODULE
44/* XXX Mega-kludge because modules are broken. */ 44/* XXX Mega-kludge because modules are broken. */
45#include <sys/once.h> 45#include <sys/once.h>
46#endif 46#endif
47#include <sys/pmf.h> 47#include <sys/pmf.h>
48#include <sys/poll.h> 48#include <sys/poll.h>
49#ifndef _MODULE 49#ifndef _MODULE
50#include <sys/reboot.h> /* XXX drm_init kludge */ 50#include <sys/reboot.h> /* XXX drm_init kludge */
51#endif 51#endif
52#include <sys/select.h> 52#include <sys/select.h>
53 53
54#include <uvm/uvm_extern.h> 54#include <uvm/uvm_extern.h>
55 55
56#include <linux/err.h> 56#include <linux/err.h>
57 57
58#include <linux/pm.h> 58#include <linux/pm.h>
59 59
60#include <drm/drmP.h> 60#include <drm/drmP.h>
61 61
62static dev_type_open(drm_open); 62static dev_type_open(drm_open);
63 63
64static int drm_firstopen(struct drm_device *); 64static int drm_firstopen(struct drm_device *);
65 65
66static int drm_close(struct file *); 66static int drm_close(struct file *);
67static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t, 67static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t,
68 int); 68 int);
69static int drm_dequeue_event(struct drm_file *, size_t, 69static int drm_dequeue_event(struct drm_file *, size_t,
70 struct drm_pending_event **, int); 70 struct drm_pending_event **, int);
71static int drm_poll(struct file *, int); 71static int drm_poll(struct file *, int);
72static int drm_kqfilter(struct file *, struct knote *); 72static int drm_kqfilter(struct file *, struct knote *);
73static int drm_stat(struct file *, struct stat *); 73static int drm_stat(struct file *, struct stat *);
74static int drm_ioctl(struct file *, unsigned long, void *); 74static int drm_ioctl(struct file *, unsigned long, void *);
75static int drm_fop_mmap(struct file *, off_t *, size_t, int, int *, int *, 75static int drm_fop_mmap(struct file *, off_t *, size_t, int, int *, int *,
76 struct uvm_object **, int *); 76 struct uvm_object **, int *);
77static int drm_version_string(char *, size_t *, const char *); 77static int drm_version_string(char *, size_t *, const char *);
78static paddr_t drm_mmap(dev_t, off_t, int); 78static paddr_t drm_mmap(dev_t, off_t, int);
79 79
80static drm_ioctl_t drm_version; 80static drm_ioctl_t drm_version;
81 81
82#define DRM_IOCTL_DEF(IOCTL, FUNC, FLAGS) \ 82#define DRM_IOCTL_DEF(IOCTL, FUNC, FLAGS) \
83 [DRM_IOCTL_NR(IOCTL)] = { \ 83 [DRM_IOCTL_NR(IOCTL)] = { \
84 .cmd = (IOCTL), \ 84 .cmd = (IOCTL), \
85 .flags = (FLAGS), \ 85 .flags = (FLAGS), \
86 .func = (FUNC), \ 86 .func = (FUNC), \
87 .cmd_drv = 0, \ 87 .cmd_drv = 0, \
88 } 88 }
89 89
90/* XXX Kludge for AGP. */ 90/* XXX Kludge for AGP. */
91static drm_ioctl_t drm_agp_acquire_hook_ioctl; 91static drm_ioctl_t drm_agp_acquire_hook_ioctl;
92static drm_ioctl_t drm_agp_release_hook_ioctl; 92static drm_ioctl_t drm_agp_release_hook_ioctl;
93static drm_ioctl_t drm_agp_enable_hook_ioctl; 93static drm_ioctl_t drm_agp_enable_hook_ioctl;
94static drm_ioctl_t drm_agp_info_hook_ioctl; 94static drm_ioctl_t drm_agp_info_hook_ioctl;
95static drm_ioctl_t drm_agp_alloc_hook_ioctl; 95static drm_ioctl_t drm_agp_alloc_hook_ioctl;
96static drm_ioctl_t drm_agp_free_hook_ioctl; 96static drm_ioctl_t drm_agp_free_hook_ioctl;
97static drm_ioctl_t drm_agp_bind_hook_ioctl; 97static drm_ioctl_t drm_agp_bind_hook_ioctl;
98static drm_ioctl_t drm_agp_unbind_hook_ioctl; 98static drm_ioctl_t drm_agp_unbind_hook_ioctl;
99 99
100#define drm_agp_acquire_ioctl drm_agp_acquire_hook_ioctl 100#define drm_agp_acquire_ioctl drm_agp_acquire_hook_ioctl
101#define drm_agp_release_ioctl drm_agp_release_hook_ioctl 101#define drm_agp_release_ioctl drm_agp_release_hook_ioctl
102#define drm_agp_enable_ioctl drm_agp_enable_hook_ioctl 102#define drm_agp_enable_ioctl drm_agp_enable_hook_ioctl
103#define drm_agp_info_ioctl drm_agp_info_hook_ioctl 103#define drm_agp_info_ioctl drm_agp_info_hook_ioctl
104#define drm_agp_alloc_ioctl drm_agp_alloc_hook_ioctl 104#define drm_agp_alloc_ioctl drm_agp_alloc_hook_ioctl
105#define drm_agp_free_ioctl drm_agp_free_hook_ioctl 105#define drm_agp_free_ioctl drm_agp_free_hook_ioctl
106#define drm_agp_bind_ioctl drm_agp_bind_hook_ioctl 106#define drm_agp_bind_ioctl drm_agp_bind_hook_ioctl
107#define drm_agp_unbind_ioctl drm_agp_unbind_hook_ioctl 107#define drm_agp_unbind_ioctl drm_agp_unbind_hook_ioctl
108 108
109/* Table copied verbatim from dist/drm/drm_drv.c. */ 109/* Table copied verbatim from dist/drm/drm_drv.c. */
110static const struct drm_ioctl_desc drm_ioctls[] = { 110static const struct drm_ioctl_desc drm_ioctls[] = {
111 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW), 111 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
112 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), 112 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
113 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), 113 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
114 DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), 114 DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
115 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED), 115 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
116 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), 116 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
117 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), 117 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
118 DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW), 118 DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
119 DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), 119 DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
120 DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), 120 DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
121 121
122 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 122 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
123 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 123 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
124 DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 124 DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
125 DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER), 125 DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
126 126
127 DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 127 DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
128 DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), 128 DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
129 129
130 DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 130 DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
131 DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), 131 DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
132 132
133 DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), 133 DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
134 DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), 134 DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
135 135
136 DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), 136 DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
137 DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 137 DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
138 DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 138 DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
139 DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), 139 DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
140 DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 140 DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
141 DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 141 DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
142 DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), 142 DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
143 143
144 DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 144 DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
145 DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 145 DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
146 146
147 DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), 147 DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
148 DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), 148 DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
149 149
150 DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), 150 DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
151 151
152 DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 152 DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
153 DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 153 DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
154 DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), 154 DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
155 DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), 155 DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
156 DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), 156 DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
157 DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH), 157 DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
158 158
159 DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 159 DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
160 160
161#if __OS_HAS_AGP 161#if __OS_HAS_AGP
162 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 162 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
163 DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 163 DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
164 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 164 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
165 DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), 165 DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
166 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 166 DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
167 DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 167 DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
168 DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 168 DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
169 DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 169 DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
170#endif 170#endif
171 171
172 DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 172 DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
173 DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 173 DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174 174
175 DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), 175 DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
176 176
177 DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), 177 DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
178 178
179 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 179 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
180 180
181 DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), 181 DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
182 DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), 182 DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
183 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), 183 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
184 184
185 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 185 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
186 186
187#ifndef __NetBSD__ /* XXX drm prime */ 187#ifndef __NetBSD__ /* XXX drm prime */
188 DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), 188 DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
189 DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), 189 DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
190#endif 190#endif
191 191
192 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 192 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
193 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 193 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
194 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 194 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
195 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 195 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
196 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 196 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
197 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 197 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
198 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED), 198 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
199 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), 199 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
200 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 200 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
201 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 201 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
202 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 202 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
203 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 203 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
204 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 204 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
205 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 205 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
206 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 206 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
207 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 207 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
208 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 208 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
209 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 209 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
210 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 210 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
211 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 211 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
212 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 212 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
213 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 213 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
214 DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 214 DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
215 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 215 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
216 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 216 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
217 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 217 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
218 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 218 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
219}; 219};
220 220
221const struct cdevsw drm_cdevsw = { 221const struct cdevsw drm_cdevsw = {
222 .d_open = drm_open, 222 .d_open = drm_open,
223 .d_close = noclose, 223 .d_close = noclose,
224 .d_read = noread, 224 .d_read = noread,
225 .d_write = nowrite, 225 .d_write = nowrite,
226 .d_ioctl = noioctl, 226 .d_ioctl = noioctl,
227 .d_stop = nostop, 227 .d_stop = nostop,
228 .d_tty = notty, 228 .d_tty = notty,
229 .d_poll = nopoll, 229 .d_poll = nopoll,
230 .d_mmap = drm_mmap, 230 .d_mmap = drm_mmap,
231 .d_kqfilter = nokqfilter, 231 .d_kqfilter = nokqfilter,
232 .d_discard = nodiscard, 232 .d_discard = nodiscard,
233 /* XXX was D_TTY | D_NEGOFFSAFE */ 233 /* XXX was D_TTY | D_NEGOFFSAFE */
234 /* XXX Add D_MPSAFE some day... */ 234 /* XXX Add D_MPSAFE some day... */
235 .d_flag = D_NEGOFFSAFE, 235 .d_flag = D_NEGOFFSAFE,
236}; 236};
237 237
238static const struct fileops drm_fileops = { 238static const struct fileops drm_fileops = {
239 .fo_read = drm_read, 239 .fo_read = drm_read,
240 .fo_write = fbadop_write, 240 .fo_write = fbadop_write,
241 .fo_ioctl = drm_ioctl, 241 .fo_ioctl = drm_ioctl,
242 .fo_fcntl = fnullop_fcntl, 242 .fo_fcntl = fnullop_fcntl,
243 .fo_poll = drm_poll, 243 .fo_poll = drm_poll,
244 .fo_stat = drm_stat, 244 .fo_stat = drm_stat,
245 .fo_close = drm_close, 245 .fo_close = drm_close,
246 .fo_kqfilter = drm_kqfilter, 246 .fo_kqfilter = drm_kqfilter,
247 .fo_restart = fnullop_restart, 247 .fo_restart = fnullop_restart,
248 .fo_mmap = drm_fop_mmap, 248 .fo_mmap = drm_fop_mmap,
249}; 249};
250 250
251static int 251static int
252drm_open(dev_t d, int flags, int fmt, struct lwp *l) 252drm_open(dev_t d, int flags, int fmt, struct lwp *l)
253{ 253{
254 struct drm_minor *dminor; 254 struct drm_minor *dminor;
255 struct drm_device *dev; 255 struct drm_device *dev;
256 bool firstopen, lastclose; 256 bool firstopen, lastclose;
257 int fd; 257 int fd;
258 struct file *fp; 258 struct file *fp;
259 int error; 259 int error;
260 extern int drm_guarantee_initialized(void); 260 extern int drm_guarantee_initialized(void);
261 261
262 error = drm_guarantee_initialized(); 262 error = drm_guarantee_initialized();
263 if (error) 263 if (error)
264 goto fail0; 264 goto fail0;
265 265
266 if (flags & O_EXCL) { 266 if (flags & O_EXCL) {
267 error = EBUSY; 267 error = EBUSY;
268 goto fail0; 268 goto fail0;
269 } 269 }
270 270
271 dminor = drm_minor_acquire(minor(d)); 271 dminor = drm_minor_acquire(minor(d));
272 if (IS_ERR(dminor)) { 272 if (IS_ERR(dminor)) {
273 /* XXX errno Linux->NetBSD */ 273 /* XXX errno Linux->NetBSD */
274 error = -PTR_ERR(dminor); 274 error = -PTR_ERR(dminor);
275 goto fail0; 275 goto fail0;
276 } 276 }
277 dev = dminor->dev; 277 dev = dminor->dev;
278 if (dev->switch_power_state != DRM_SWITCH_POWER_ON) { 278 if (dev->switch_power_state != DRM_SWITCH_POWER_ON) {
279 error = EINVAL; 279 error = EINVAL;
280 goto fail1; 280 goto fail1;
281 } 281 }
282 282
283 spin_lock(&dev->count_lock); 283 spin_lock(&dev->count_lock);
284 if (dev->open_count == INT_MAX) { 284 if (dev->open_count == INT_MAX) {
285 spin_unlock(&dev->count_lock); 285 spin_unlock(&dev->count_lock);
286 error = EBUSY; 286 error = EBUSY;
287 goto fail1; 287 goto fail1;
288 } 288 }
289 firstopen = (dev->open_count == 0); 289 firstopen = (dev->open_count == 0);
290 dev->open_count++; 290 dev->open_count++;
291 spin_unlock(&dev->count_lock); 291 spin_unlock(&dev->count_lock);
292 292
293 if (firstopen) { 293 if (firstopen) {
294 /* XXX errno Linux->NetBSD */ 294 /* XXX errno Linux->NetBSD */
295 error = drm_firstopen(dev); 295 error = drm_firstopen(dev);
296 if (error) 296 if (error)
297 goto fail2; 297 goto fail2;
298 } 298 }
299 299
300 error = fd_allocfile(&fp, &fd); 300 error = fd_allocfile(&fp, &fd);
301 if (error) 301 if (error)
302 goto fail2; 302 goto fail2;
303 303
304 struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP); 304 struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP);
305 /* XXX errno Linux->NetBSD */ 305 /* XXX errno Linux->NetBSD */
306 error = -drm_open_file(file, fp, dminor); 306 error = -drm_open_file(file, fp, dminor);
307 if (error) 307 if (error)
308 goto fail3; 308 goto fail3;
309 309
310 error = fd_clone(fp, fd, flags, &drm_fileops, file); 310 error = fd_clone(fp, fd, flags, &drm_fileops, file);
311 KASSERT(error == EMOVEFD); /* XXX */ 311 KASSERT(error == EMOVEFD); /* XXX */
312 312
313 /* Success! (But error has to be EMOVEFD, not 0.) */ 313 /* Success! (But error has to be EMOVEFD, not 0.) */
314 return error; 314 return error;
315 315
316fail3: kmem_free(file, sizeof(*file)); 316fail3: kmem_free(file, sizeof(*file));
317 fd_abort(curproc, fp, fd); 317 fd_abort(curproc, fp, fd);
318fail2: spin_lock(&dev->count_lock); 318fail2: spin_lock(&dev->count_lock);
319 KASSERT(0 < dev->open_count); 319 KASSERT(0 < dev->open_count);
320 --dev->open_count; 320 --dev->open_count;
321 lastclose = (dev->open_count == 0); 321 lastclose = (dev->open_count == 0);
322 spin_unlock(&dev->count_lock); 322 spin_unlock(&dev->count_lock);
323 if (lastclose) 323 if (lastclose)
324 (void)drm_lastclose(dev); 324 (void)drm_lastclose(dev);
325fail1: drm_minor_release(dminor); 325fail1: drm_minor_release(dminor);
326fail0: KASSERT(error); 326fail0: KASSERT(error);
327 return error; 327 return error;
328} 328}
329 329
330static int 330static int
331drm_close(struct file *fp) 331drm_close(struct file *fp)
332{ 332{
333 struct drm_file *const file = fp->f_data; 333 struct drm_file *const file = fp->f_data;
334 struct drm_minor *const dminor = file->minor; 334 struct drm_minor *const dminor = file->minor;
335 struct drm_device *const dev = dminor->dev; 335 struct drm_device *const dev = dminor->dev;
336 bool lastclose; 336 bool lastclose;
337 337
338 drm_close_file(file); 338 drm_close_file(file);
339 kmem_free(file, sizeof(*file)); 339 kmem_free(file, sizeof(*file));
340 340
341 spin_lock(&dev->count_lock); 341 spin_lock(&dev->count_lock);
342 KASSERT(0 < dev->open_count); 342 KASSERT(0 < dev->open_count);
343 --dev->open_count; 343 --dev->open_count;
344 lastclose = (dev->open_count == 0); 344 lastclose = (dev->open_count == 0);
345 spin_unlock(&dev->count_lock); 345 spin_unlock(&dev->count_lock);
346 346
347 if (lastclose) 347 if (lastclose)
348 (void)drm_lastclose(dev); 348 (void)drm_lastclose(dev);
349 349
350 drm_minor_release(dminor); 350 drm_minor_release(dminor);
351 351
352 return 0; 352 return 0;
353} 353}
354 354
355static int 355static int
356drm_firstopen(struct drm_device *dev) 356drm_firstopen(struct drm_device *dev)
357{ 357{
358 int ret; 358 int ret;
359 359
360 if (drm_core_check_feature(dev, DRIVER_MODESET)) 360 if (drm_core_check_feature(dev, DRIVER_MODESET))
361 return 0; 361 return 0;
362 362
363 if (dev->driver->firstopen) { 363 if (dev->driver->firstopen) {
364 ret = (*dev->driver->firstopen)(dev); 364 ret = (*dev->driver->firstopen)(dev);
365 if (ret) 365 if (ret)
366 goto fail0; 366 goto fail0;
367 } 367 }
368 368
369 ret = drm_legacy_dma_setup(dev); 369 ret = drm_legacy_dma_setup(dev);
370 if (ret) 370 if (ret)
371 goto fail1; 371 goto fail1;
372 372
373 return 0; 373 return 0;
374 374
375fail2: __unused 375fail2: __unused
376 drm_legacy_dma_takedown(dev); 376 drm_legacy_dma_takedown(dev);
377fail1: if (dev->driver->lastclose) 377fail1: if (dev->driver->lastclose)
378 (*dev->driver->lastclose)(dev); 378 (*dev->driver->lastclose)(dev);
379fail0: KASSERT(ret); 379fail0: KASSERT(ret);
380 return ret; 380 return ret;
381} 381}
382 382
383int 383int
384drm_lastclose(struct drm_device *dev) 384drm_lastclose(struct drm_device *dev)
385{ 385{
386 struct drm_vma_entry *vma, *vma_temp; 386 struct drm_vma_entry *vma, *vma_temp;
387 387
388 /* XXX Order is sketchy here... */ 388 /* XXX Order is sketchy here... */
389 if (dev->driver->lastclose) 389 if (dev->driver->lastclose)
390 (*dev->driver->lastclose)(dev); 390 (*dev->driver->lastclose)(dev);
391 if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) 391 if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
392 drm_irq_uninstall(dev); 392 drm_irq_uninstall(dev);
393 393
394 mutex_lock(&dev->struct_mutex); 394 mutex_lock(&dev->struct_mutex);
395 drm_agp_clear_hook(dev); 395 drm_agp_clear_hook(dev);
396 drm_legacy_sg_cleanup(dev); 396 drm_legacy_sg_cleanup(dev);
397 list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) { 397 list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
398 list_del(&vma->head); 398 list_del(&vma->head);
399 kfree(vma); 399 kfree(vma);
400 } 400 }
401 drm_legacy_dma_takedown(dev); 401 drm_legacy_dma_takedown(dev);
402 mutex_unlock(&dev->struct_mutex); 402 mutex_unlock(&dev->struct_mutex);
403 403
404 if (!drm_core_check_feature(dev, DRIVER_MODESET)) { 404 if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
405 dev->sigdata.lock = NULL; 405 dev->sigdata.lock = NULL;
406 dev->context_flag = 0; 406 dev->context_flag = 0;
407 dev->last_context = 0; 407 dev->last_context = 0;
408 dev->if_version = 0; 408 dev->if_version = 0;
409 } 409 }
410 410
411 return 0; 411 return 0;
412} 412}
413 413
414static int 414static int
415drm_read(struct file *fp, off_t *off, struct uio *uio, kauth_cred_t cred, 415drm_read(struct file *fp, off_t *off, struct uio *uio, kauth_cred_t cred,
416 int flags) 416 int flags)
417{ 417{
418 struct drm_file *const file = fp->f_data; 418 struct drm_file *const file = fp->f_data;
419 struct drm_pending_event *event; 419 struct drm_pending_event *event;
420 bool first; 420 bool first;
421 int error = 0; 421 int error = 0;
422 422
423 for (first = true; ; first = false) { 423 for (first = true; ; first = false) {
424 int f = 0; 424 int f = 0;
425 425
426 if (!first || ISSET(fp->f_flag, FNONBLOCK)) 426 if (!first || ISSET(fp->f_flag, FNONBLOCK))
427 f |= FNONBLOCK; 427 f |= FNONBLOCK;
428 428
429 /* XXX errno Linux->NetBSD */ 429 /* XXX errno Linux->NetBSD */
430 error = -drm_dequeue_event(file, uio->uio_resid, &event, f); 430 error = -drm_dequeue_event(file, uio->uio_resid, &event, f);
431 if (error) { 431 if (error) {
432 if ((error == EWOULDBLOCK) && !first) 432 if ((error == EWOULDBLOCK) && !first)
433 error = 0; 433 error = 0;
434 break; 434 break;
435 } 435 }
436 if (event == NULL) 436 if (event == NULL)
437 break; 437 break;
438 error = uiomove(event->event, event->event->length, uio); 438 error = uiomove(event->event, event->event->length, uio);
439 if (error) /* XXX Requeue the event? */ 439 if (error) /* XXX Requeue the event? */
440 break; 440 break;
441 (*event->destroy)(event); 441 (*event->destroy)(event);
442 } 442 }
443 443
444 /* Success! */ 444 /* Success! */
445 return error; 445 return error;
446} 446}
447 447
448static int 448static int
449drm_dequeue_event(struct drm_file *file, size_t max_length, 449drm_dequeue_event(struct drm_file *file, size_t max_length,
450 struct drm_pending_event **eventp, int flags) 450 struct drm_pending_event **eventp, int flags)
451{ 451{
452 struct drm_device *const dev = file->minor->dev; 452 struct drm_device *const dev = file->minor->dev;
453 struct drm_pending_event *event = NULL; 453 struct drm_pending_event *event = NULL;
454 unsigned long irqflags; 454 unsigned long irqflags;
455 int ret = 0; 455 int ret = 0;
456 456
457 spin_lock_irqsave(&dev->event_lock, irqflags); 457 spin_lock_irqsave(&dev->event_lock, irqflags);
458 458
459 if (ISSET(flags, FNONBLOCK)) { 459 if (ISSET(flags, FNONBLOCK)) {
460 if (list_empty(&file->event_list)) 460 if (list_empty(&file->event_list))
461 ret = -EWOULDBLOCK; 461 ret = -EWOULDBLOCK;
462 } else { 462 } else {
463 DRM_SPIN_WAIT_UNTIL(ret, &file->event_wait, &dev->event_lock, 463 DRM_SPIN_WAIT_UNTIL(ret, &file->event_wait, &dev->event_lock,
464 !list_empty(&file->event_list)); 464 !list_empty(&file->event_list));
465 } 465 }
466 if (ret) 466 if (ret)
467 goto out; 467 goto out;
468 468
469 event = list_first_entry(&file->event_list, struct drm_pending_event, 469 event = list_first_entry(&file->event_list, struct drm_pending_event,
470 link); 470 link);
471 if (event->event->length > max_length) { 471 if (event->event->length > max_length) {
472 ret = 0; 472 ret = 0;
473 goto out; 473 goto out;
474 } 474 }
475 475
476 file->event_space += event->event->length; 476 file->event_space += event->event->length;
477 list_del(&event->link); 477 list_del(&event->link);
478 478
479out: spin_unlock_irqrestore(&dev->event_lock, irqflags); 479out: spin_unlock_irqrestore(&dev->event_lock, irqflags);
480 *eventp = event; 480 *eventp = event;
481 return ret; 481 return ret;
482} 482}
483 483
484static int 484static int
485drm_poll(struct file *fp __unused, int events __unused) 485drm_poll(struct file *fp __unused, int events __unused)
486{ 486{
487 struct drm_file *const file = fp->f_data; 487 struct drm_file *const file = fp->f_data;
488 struct drm_device *const dev = file->minor->dev; 488 struct drm_device *const dev = file->minor->dev;
489 int revents = 0; 489 int revents = 0;
490 unsigned long irqflags; 490 unsigned long irqflags;
491 491
492 if (!ISSET(events, (POLLIN | POLLRDNORM))) 492 if (!ISSET(events, (POLLIN | POLLRDNORM)))
493 return 0; 493 return 0;
494 494
495 spin_lock_irqsave(&dev->event_lock, irqflags); 495 spin_lock_irqsave(&dev->event_lock, irqflags);
496 if (list_empty(&file->event_list)) 496 if (list_empty(&file->event_list))
497 selrecord(curlwp, &file->event_selq); 497 selrecord(curlwp, &file->event_selq);
498 else 498 else
499 revents |= (events & (POLLIN | POLLRDNORM)); 499 revents |= (events & (POLLIN | POLLRDNORM));
500 spin_unlock_irqrestore(&dev->event_lock, irqflags); 500 spin_unlock_irqrestore(&dev->event_lock, irqflags);
501 501
502 return revents; 502 return revents;
503} 503}
504 504
505static void filt_drm_detach(struct knote *); 505static void filt_drm_detach(struct knote *);
506static int filt_drm_event(struct knote *, long); 506static int filt_drm_event(struct knote *, long);
507 507
508static const struct filterops drm_filtops = 508static const struct filterops drm_filtops =
509 { 1, NULL, filt_drm_detach, filt_drm_event }; 509 { 1, NULL, filt_drm_detach, filt_drm_event };
510 510
511static int 511static int
512drm_kqfilter(struct file *fp, struct knote *kn) 512drm_kqfilter(struct file *fp, struct knote *kn)
513{ 513{
514 struct drm_file *const file = fp->f_data; 514 struct drm_file *const file = fp->f_data;
515 struct drm_device *const dev = file->minor->dev; 515 struct drm_device *const dev = file->minor->dev;
516 unsigned long irqflags; 516 unsigned long irqflags;
517 517
518 switch (kn->kn_filter) { 518 switch (kn->kn_filter) {
519 case EVFILT_READ: 519 case EVFILT_READ:
520 kn->kn_fop = &drm_filtops; 520 kn->kn_fop = &drm_filtops;
521 kn->kn_hook = file; 521 kn->kn_hook = file;
522 spin_lock_irqsave(&dev->event_lock, irqflags); 522 spin_lock_irqsave(&dev->event_lock, irqflags);
523 SLIST_INSERT_HEAD(&file->event_selq.sel_klist, kn, kn_selnext); 523 SLIST_INSERT_HEAD(&file->event_selq.sel_klist, kn, kn_selnext);
524 spin_unlock_irqrestore(&dev->event_lock, irqflags); 524 spin_unlock_irqrestore(&dev->event_lock, irqflags);
525 return 0; 525 return 0;
526 case EVFILT_WRITE: 526 case EVFILT_WRITE:
527 default: 527 default:
528 return EINVAL; 528 return EINVAL;
529 } 529 }
530} 530}
531 531
532static void 532static void
533filt_drm_detach(struct knote *kn) 533filt_drm_detach(struct knote *kn)
534{ 534{
535 struct drm_file *const file = kn->kn_hook; 535 struct drm_file *const file = kn->kn_hook;
536 struct drm_device *const dev = file->minor->dev; 536 struct drm_device *const dev = file->minor->dev;
537 unsigned long irqflags; 537 unsigned long irqflags;
538 538
539 spin_lock_irqsave(&dev->event_lock, irqflags); 539 spin_lock_irqsave(&dev->event_lock, irqflags);
540 SLIST_REMOVE(&file->event_selq.sel_klist, kn, knote, kn_selnext); 540 SLIST_REMOVE(&file->event_selq.sel_klist, kn, knote, kn_selnext);
541 spin_unlock_irqrestore(&dev->event_lock, irqflags); 541 spin_unlock_irqrestore(&dev->event_lock, irqflags);
542} 542}
543 543
544static int 544static int
545filt_drm_event(struct knote *kn, long hint) 545filt_drm_event(struct knote *kn, long hint)
546{ 546{
547 struct drm_file *const file = kn->kn_hook; 547 struct drm_file *const file = kn->kn_hook;
548 struct drm_device *const dev = file->minor->dev; 548 struct drm_device *const dev = file->minor->dev;
549 unsigned long irqflags; 549 unsigned long irqflags;
550 int ret; 550 int ret;
551 551
552 if (hint == NOTE_SUBMIT) 552 if (hint == NOTE_SUBMIT)
553 KASSERT(spin_is_locked(&dev->event_lock)); 553 KASSERT(spin_is_locked(&dev->event_lock));
554 else 554 else
555 spin_lock_irqsave(&dev->event_lock, irqflags); 555 spin_lock_irqsave(&dev->event_lock, irqflags);
556 if (list_empty(&file->event_list)) { 556 if (list_empty(&file->event_list)) {
557 ret = 0; 557 ret = 0;
558 } else { 558 } else {
559 struct drm_pending_event *const event = 559 struct drm_pending_event *const event =
560 list_first_entry(&file->event_list, 560 list_first_entry(&file->event_list,
561 struct drm_pending_event, link); 561 struct drm_pending_event, link);
562 kn->kn_data = event->event->length; 562 kn->kn_data = event->event->length;
563 ret = 1; 563 ret = 1;
564 } 564 }
565 if (hint == NOTE_SUBMIT) 565 if (hint == NOTE_SUBMIT)
566 KASSERT(spin_is_locked(&dev->event_lock)); 566 KASSERT(spin_is_locked(&dev->event_lock));
567 else 567 else
568 spin_unlock_irqrestore(&dev->event_lock, irqflags); 568 spin_unlock_irqrestore(&dev->event_lock, irqflags);
569 569
570 return ret; 570 return ret;
571} 571}
572 572
573static int 573static int
574drm_stat(struct file *fp, struct stat *st) 574drm_stat(struct file *fp, struct stat *st)
575{ 575{
576 struct drm_file *const file = fp->f_data; 576 struct drm_file *const file = fp->f_data;
577 struct drm_minor *const dminor = file->minor; 577 struct drm_minor *const dminor = file->minor;
578 const dev_t devno = makedev(cdevsw_lookup_major(&drm_cdevsw), 578 const dev_t devno = makedev(cdevsw_lookup_major(&drm_cdevsw),
579 64*dminor->index + dminor->type); 579 64*dminor->index + dminor->type);
580 580
581 (void)memset(st, 0, sizeof(*st)); 581 (void)memset(st, 0, sizeof(*st));
582 582
583 st->st_dev = devno; 583 st->st_dev = devno;
584 st->st_ino = 0; /* XXX (dev,ino) uniqueness bleh */ 584 st->st_ino = 0; /* XXX (dev,ino) uniqueness bleh */
585 st->st_uid = kauth_cred_geteuid(fp->f_cred); 585 st->st_uid = kauth_cred_geteuid(fp->f_cred);
586 st->st_gid = kauth_cred_getegid(fp->f_cred); 586 st->st_gid = kauth_cred_getegid(fp->f_cred);
587 st->st_mode = S_IFCHR; /* XXX what? */ 587 st->st_mode = S_IFCHR; /* XXX what? */
588 st->st_rdev = devno; 588 st->st_rdev = devno;
589 /* XXX what else? */ 589 /* XXX what else? */
590 590
591 return 0; 591 return 0;
592} 592}
593 593
594static int 594static int
595drm_ioctl(struct file *fp, unsigned long cmd, void *data) 595drm_ioctl(struct file *fp, unsigned long cmd, void *data)
596{ 596{
597 struct drm_file *const file = fp->f_data; 597 struct drm_file *const file = fp->f_data;
598 const unsigned int nr = DRM_IOCTL_NR(cmd); 598 const unsigned int nr = DRM_IOCTL_NR(cmd);
599 int error; 599 int error;
600 600
601 switch (cmd) { 601 switch (cmd) {
602 case FIONBIO: 602 case FIONBIO:
603 case FIOASYNC: 603 case FIOASYNC:
604 return 0; 604 return 0;
605 605
606#if 0 /* XXX why? */ 606#if 0 /* XXX why? */
607 case SIOCSPGRP: 607 case SIOCSPGRP:
608 case TIOCSPGRP: 608 case TIOCSPGRP:
609 case FIOSETOWN: 609 case FIOSETOWN:
610 return fsetown(&dev->buf_pgid, cmd, data); 610 return fsetown(&dev->buf_pgid, cmd, data);
611 611
612 case SIOCGPGRP: 612 case SIOCGPGRP:
613 case TIOCGPGRP: 613 case TIOCGPGRP:
614 case FIOGETOWN: 614 case FIOGETOWN:
615 return fgetown(&dev->buf_pgid, cmd, data); 615 return fgetown(&dev->buf_pgid, cmd, data);
616#endif 616#endif
617 617
618 default: 618 default:
619 break; 619 break;
620 } 620 }
621 621
622 if (IOCGROUP(cmd) != DRM_IOCTL_BASE) 622 if (IOCGROUP(cmd) != DRM_IOCTL_BASE)
623 return EINVAL; 623 return EINVAL;
624 624
625 KASSERT(file != NULL); 625 KASSERT(file != NULL);
626 KASSERT(file->minor != NULL); 626 KASSERT(file->minor != NULL);
627 KASSERT(file->minor->dev != NULL); 627 KASSERT(file->minor->dev != NULL);
628 struct drm_device *const dev = file->minor->dev; 628 struct drm_device *const dev = file->minor->dev;
629 const struct drm_ioctl_desc *ioctl; 629 const struct drm_ioctl_desc *ioctl;
630 630
631 if ((DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END)) { 631 if ((DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END)) {
632 const unsigned int driver_nr = nr - DRM_COMMAND_BASE; 632 const unsigned int driver_nr = nr - DRM_COMMAND_BASE;
633 if (driver_nr >= dev->driver->num_ioctls) 633 if (driver_nr >= dev->driver->num_ioctls)
634 return EINVAL; 634 return EINVAL;
635 ioctl = &dev->driver->ioctls[driver_nr]; 635 ioctl = &dev->driver->ioctls[driver_nr];
636 } else if (nr < __arraycount(drm_ioctls)) { 636 } else if (nr < __arraycount(drm_ioctls)) {
637 ioctl = &drm_ioctls[nr]; 637 ioctl = &drm_ioctls[nr];
638 } else { 638 } else {
639 ioctl = NULL; 639 ioctl = NULL;
640 } 640 }
641 641
642 if ((ioctl == NULL) || (ioctl->func == NULL)) 642 if ((ioctl == NULL) || (ioctl->func == NULL))
643 return EINVAL; 643 return EINVAL;
644 644
 645 /* XXX Synchronize with drm_ioctl_permit in upstream drm_drv.c. */
645 if (ISSET(ioctl->flags, DRM_ROOT_ONLY) && !DRM_SUSER()) 646 if (ISSET(ioctl->flags, DRM_ROOT_ONLY) && !DRM_SUSER())
646 return EACCES; 647 return EACCES;
647 648
648 if (ISSET(ioctl->flags, DRM_AUTH) && !file->authenticated) 649 if (ISSET(ioctl->flags, DRM_AUTH) &&
 650 (file->minor->type != DRM_MINOR_RENDER) &&
 651 !file->authenticated)
649 return EACCES; 652 return EACCES;
650 653
651 if (ISSET(ioctl->flags, DRM_MASTER) && (file->master == NULL)) 654 if (ISSET(ioctl->flags, DRM_MASTER) &&
 655 (file->master == NULL) &&
 656 (file->minor->type != DRM_MINOR_CONTROL))
652 return EACCES; 657 return EACCES;
653 658
654 if (!ISSET(ioctl->flags, DRM_CONTROL_ALLOW) && 659 if (!ISSET(ioctl->flags, DRM_CONTROL_ALLOW) &&
655 (file->minor->type == DRM_MINOR_CONTROL)) 660 (file->minor->type == DRM_MINOR_CONTROL))
656 return EACCES; 661 return EACCES;
657 662
 663 if (!ISSET(ioctl->flags, DRM_RENDER_ALLOW) &&
 664 (file->minor->type == DRM_MINOR_RENDER))
 665 return EACCES;
 666
658 if (!ISSET(ioctl->flags, DRM_UNLOCKED)) 667 if (!ISSET(ioctl->flags, DRM_UNLOCKED))
659 mutex_lock(&drm_global_mutex); 668 mutex_lock(&drm_global_mutex);
660 669
661 /* XXX errno Linux->NetBSD */ 670 /* XXX errno Linux->NetBSD */
662 error = -(*ioctl->func)(dev, data, file); 671 error = -(*ioctl->func)(dev, data, file);
663 672
664 if (!ISSET(ioctl->flags, DRM_UNLOCKED)) 673 if (!ISSET(ioctl->flags, DRM_UNLOCKED))
665 mutex_unlock(&drm_global_mutex); 674 mutex_unlock(&drm_global_mutex);
666 675
667 return error; 676 return error;
668} 677}
669 678
670static int 679static int
671drm_fop_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp, 680drm_fop_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp,
672 int *advicep, struct uvm_object **uobjp, int *maxprotp) 681 int *advicep, struct uvm_object **uobjp, int *maxprotp)
673{ 682{
674 struct drm_file *const file = fp->f_data; 683 struct drm_file *const file = fp->f_data;
675 struct drm_device *const dev = file->minor->dev; 684 struct drm_device *const dev = file->minor->dev;
676 int error; 685 int error;
677 686
678 KASSERT(fp == file->filp); 687 KASSERT(fp == file->filp);
679 error = (*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp, 688 error = (*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp,
680 offp, file->filp); 689 offp, file->filp);
681 *maxprotp = prot; 690 *maxprotp = prot;
682 *advicep = UVM_ADV_RANDOM; 691 *advicep = UVM_ADV_RANDOM;
683 return -error; 692 return -error;
684} 693}
685 694
686static int 695static int
687drm_version_string(char *target, size_t *lenp, const char *source) 696drm_version_string(char *target, size_t *lenp, const char *source)
688{ 697{
689 const size_t len = strlen(source); 698 const size_t len = strlen(source);
690 const size_t trunc_len = MIN(len, *lenp); 699 const size_t trunc_len = MIN(len, *lenp);
691 700
692 *lenp = len; 701 *lenp = len;
693 if ((trunc_len > 0) && (target != NULL)) 702 if ((trunc_len > 0) && (target != NULL))
694 /* copyoutstr takes a buffer size, not a string length. */ 703 /* copyoutstr takes a buffer size, not a string length. */
695 /* XXX errno NetBSD->Linux */ 704 /* XXX errno NetBSD->Linux */
696 return -copyoutstr(source, target, trunc_len+1, NULL); 705 return -copyoutstr(source, target, trunc_len+1, NULL);
697 706
698 return 0; 707 return 0;
699} 708}
700 709
701static int 710static int
702drm_version(struct drm_device *dev, void *data, struct drm_file *file) 711drm_version(struct drm_device *dev, void *data, struct drm_file *file)
703{ 712{
704 struct drm_version *v = data; 713 struct drm_version *v = data;
705 int error; 714 int error;
706 715
707 v->version_major = dev->driver->major; 716 v->version_major = dev->driver->major;
708 v->version_minor = dev->driver->minor; 717 v->version_minor = dev->driver->minor;
709 v->version_patchlevel = dev->driver->patchlevel; 718 v->version_patchlevel = dev->driver->patchlevel;
710 719
711 error = drm_version_string(v->name, &v->name_len, dev->driver->name); 720 error = drm_version_string(v->name, &v->name_len, dev->driver->name);
712 if (error) 721 if (error)
713 goto out; 722 goto out;
714 error = drm_version_string(v->date, &v->date_len, dev->driver->date); 723 error = drm_version_string(v->date, &v->date_len, dev->driver->date);
715 if (error) 724 if (error)
716 goto out; 725 goto out;
717 error = drm_version_string(v->desc, &v->desc_len, dev->driver->desc); 726 error = drm_version_string(v->desc, &v->desc_len, dev->driver->desc);
718 if (error) 727 if (error)
719 goto out; 728 goto out;
720 729
721out: return error; 730out: return error;
722} 731}
723 732
724static paddr_t 733static paddr_t
725drm_mmap(dev_t d, off_t offset, int prot) 734drm_mmap(dev_t d, off_t offset, int prot)
726{ 735{
727 struct drm_minor *dminor; 736 struct drm_minor *dminor;
728 paddr_t paddr; 737 paddr_t paddr;
729 738
730 dminor = drm_minor_acquire(minor(d)); 739 dminor = drm_minor_acquire(minor(d));
731 if (IS_ERR(dminor)) 740 if (IS_ERR(dminor))
732 return (paddr_t)-1; 741 return (paddr_t)-1;
733 742
734 paddr = drm_mmap_paddr(dminor->dev, offset, prot); 743 paddr = drm_mmap_paddr(dminor->dev, offset, prot);
735 744
736 drm_minor_release(dminor); 745 drm_minor_release(dminor);
737 return paddr; 746 return paddr;
738} 747}
739 748
740static const struct drm_agp_hooks *volatile drm_current_agp_hooks; 749static const struct drm_agp_hooks *volatile drm_current_agp_hooks;
741 750
742int 751int
743drm_agp_register(const struct drm_agp_hooks *hooks) 752drm_agp_register(const struct drm_agp_hooks *hooks)
744{ 753{
745 754
746 membar_producer(); 755 membar_producer();
747 if (atomic_cas_ptr(&drm_current_agp_hooks, NULL, __UNCONST(hooks)) 756 if (atomic_cas_ptr(&drm_current_agp_hooks, NULL, __UNCONST(hooks))
748 != NULL) 757 != NULL)
749 return EBUSY; 758 return EBUSY;
750 759
751 return 0; 760 return 0;
752} 761}
753 762
754void 763void
755drm_agp_deregister(const struct drm_agp_hooks *hooks) 764drm_agp_deregister(const struct drm_agp_hooks *hooks)
756{ 765{
757 766
758 if (atomic_cas_ptr(&drm_current_agp_hooks, __UNCONST(hooks), NULL) 767 if (atomic_cas_ptr(&drm_current_agp_hooks, __UNCONST(hooks), NULL)
759 != hooks) 768 != hooks)
760 panic("%s: wrong hooks: %p != %p", __func__, 769 panic("%s: wrong hooks: %p != %p", __func__,
761 hooks, drm_current_agp_hooks); 770 hooks, drm_current_agp_hooks);
762} 771}
763 772
764static void __dead 773static void __dead
765drm_noagp_panic(struct drm_device *dev) 774drm_noagp_panic(struct drm_device *dev)
766{ 775{
767 if ((dev != NULL) && 776 if ((dev != NULL) &&
768 (dev->control != NULL) && 777 (dev->control != NULL) &&
769 (dev->control->kdev != NULL)) 778 (dev->control->kdev != NULL))
770 panic("%s: no agp loaded", device_xname(dev->control->kdev)); 779 panic("%s: no agp loaded", device_xname(dev->control->kdev));
771 else 780 else
772 panic("drm_device %p: no agp loaded", dev); 781 panic("drm_device %p: no agp loaded", dev);
773} 782}
774 783
775int 784int
776drm_agp_release_hook(struct drm_device *dev) 785drm_agp_release_hook(struct drm_device *dev)
777{ 786{
778 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks; 787 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks;
779 788
780 if (hooks == NULL) 789 if (hooks == NULL)
781 drm_noagp_panic(dev); 790 drm_noagp_panic(dev);
782 membar_consumer(); 791 membar_consumer();
783 return (*hooks->agph_release)(dev); 792 return (*hooks->agph_release)(dev);
784} 793}
785 794
786void 795void
787drm_agp_clear_hook(struct drm_device *dev) 796drm_agp_clear_hook(struct drm_device *dev)
788{ 797{
789 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks; 798 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks;
790 799
791 if (hooks == NULL) 800 if (hooks == NULL)
792 drm_noagp_panic(dev); 801 drm_noagp_panic(dev);
793 membar_consumer(); 802 membar_consumer();
794 (*hooks->agph_clear)(dev); 803 (*hooks->agph_clear)(dev);
795} 804}
796 805
797#define DEFINE_AGP_HOOK_IOCTL(NAME, HOOK) \ 806#define DEFINE_AGP_HOOK_IOCTL(NAME, HOOK) \
798static int \ 807static int \
799NAME(struct drm_device *dev, void *data, struct drm_file *file) \ 808NAME(struct drm_device *dev, void *data, struct drm_file *file) \
800{ \ 809{ \
801 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks; \ 810 const struct drm_agp_hooks *const hooks = drm_current_agp_hooks; \
802 \ 811 \
803 if (hooks == NULL) \ 812 if (hooks == NULL) \
804 return -ENODEV; \ 813 return -ENODEV; \
805 membar_consumer(); \ 814 membar_consumer(); \
806 return (*hooks->HOOK)(dev, data, file); \ 815 return (*hooks->HOOK)(dev, data, file); \
807} 816}
808 817
809DEFINE_AGP_HOOK_IOCTL(drm_agp_acquire_hook_ioctl, agph_acquire_ioctl) 818DEFINE_AGP_HOOK_IOCTL(drm_agp_acquire_hook_ioctl, agph_acquire_ioctl)
810DEFINE_AGP_HOOK_IOCTL(drm_agp_release_hook_ioctl, agph_release_ioctl) 819DEFINE_AGP_HOOK_IOCTL(drm_agp_release_hook_ioctl, agph_release_ioctl)
811DEFINE_AGP_HOOK_IOCTL(drm_agp_enable_hook_ioctl, agph_enable_ioctl) 820DEFINE_AGP_HOOK_IOCTL(drm_agp_enable_hook_ioctl, agph_enable_ioctl)
812DEFINE_AGP_HOOK_IOCTL(drm_agp_info_hook_ioctl, agph_info_ioctl) 821DEFINE_AGP_HOOK_IOCTL(drm_agp_info_hook_ioctl, agph_info_ioctl)
813DEFINE_AGP_HOOK_IOCTL(drm_agp_alloc_hook_ioctl, agph_alloc_ioctl) 822DEFINE_AGP_HOOK_IOCTL(drm_agp_alloc_hook_ioctl, agph_alloc_ioctl)
814DEFINE_AGP_HOOK_IOCTL(drm_agp_free_hook_ioctl, agph_free_ioctl) 823DEFINE_AGP_HOOK_IOCTL(drm_agp_free_hook_ioctl, agph_free_ioctl)
815DEFINE_AGP_HOOK_IOCTL(drm_agp_bind_hook_ioctl, agph_bind_ioctl) 824DEFINE_AGP_HOOK_IOCTL(drm_agp_bind_hook_ioctl, agph_bind_ioctl)
816DEFINE_AGP_HOOK_IOCTL(drm_agp_unbind_hook_ioctl, agph_unbind_ioctl) 825DEFINE_AGP_HOOK_IOCTL(drm_agp_unbind_hook_ioctl, agph_unbind_ioctl)