| @@ -1,1105 +1,1121 @@ | | | @@ -1,1105 +1,1121 @@ |
1 | /* $NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $ */ | | 1 | /* $NetBSD: drm_ioctl.c,v 1.25 2024/04/21 03:02:51 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com | | 4 | * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com |
5 | * | | 5 | * |
6 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | | 6 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
7 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | | 7 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
8 | * All Rights Reserved. | | 8 | * All Rights Reserved. |
9 | * | | 9 | * |
10 | * Author Rickard E. (Rik) Faith <faith@valinux.com> | | 10 | * Author Rickard E. (Rik) Faith <faith@valinux.com> |
11 | * Author Gareth Hughes <gareth@valinux.com> | | 11 | * Author Gareth Hughes <gareth@valinux.com> |
12 | * | | 12 | * |
13 | * Permission is hereby granted, free of charge, to any person obtaining a | | 13 | * Permission is hereby granted, free of charge, to any person obtaining a |
14 | * copy of this software and associated documentation files (the "Software"), | | 14 | * copy of this software and associated documentation files (the "Software"), |
15 | * to deal in the Software without restriction, including without limitation | | 15 | * to deal in the Software without restriction, including without limitation |
16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | | 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
17 | * and/or sell copies of the Software, and to permit persons to whom the | | 17 | * and/or sell copies of the Software, and to permit persons to whom the |
18 | * Software is furnished to do so, subject to the following conditions: | | 18 | * Software is furnished to do so, subject to the following conditions: |
19 | * | | 19 | * |
20 | * The above copyright notice and this permission notice (including the next | | 20 | * The above copyright notice and this permission notice (including the next |
21 | * paragraph) shall be included in all copies or substantial portions of the | | 21 | * paragraph) shall be included in all copies or substantial portions of the |
22 | * Software. | | 22 | * Software. |
23 | * | | 23 | * |
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | | 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | | 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | | 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
27 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | | 27 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
28 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | | 28 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
29 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | | 29 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
30 | * OTHER DEALINGS IN THE SOFTWARE. | | 30 | * OTHER DEALINGS IN THE SOFTWARE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.25 2024/04/21 03:02:51 riastradh Exp $"); |
35 | | | 35 | |
36 | #include <linux/export.h> | | 36 | #include <linux/export.h> |
37 | #include <linux/nospec.h> | | 37 | #include <linux/nospec.h> |
38 | #include <linux/pci.h> | | 38 | #include <linux/pci.h> |
39 | #include <linux/uaccess.h> | | 39 | #include <linux/uaccess.h> |
40 | #include <linux/capability.h> | | 40 | #include <linux/capability.h> |
41 | | | 41 | |
42 | #ifdef __NetBSD__ | | 42 | #ifdef __NetBSD__ |
43 | #include <sys/types.h> | | 43 | #include <sys/types.h> |
44 | #include <sys/file.h> | | 44 | #include <sys/file.h> |
45 | #endif | | 45 | #endif |
46 | | | 46 | |
47 | #include <drm/drm_agpsupport.h> | | 47 | #include <drm/drm_agpsupport.h> |
48 | #include <drm/drm_auth.h> | | 48 | #include <drm/drm_auth.h> |
49 | #include <drm/drm_crtc.h> | | 49 | #include <drm/drm_crtc.h> |
50 | #include <drm/drm_drv.h> | | 50 | #include <drm/drm_drv.h> |
51 | #include <drm/drm_file.h> | | 51 | #include <drm/drm_file.h> |
52 | #include <drm/drm_ioctl.h> | | 52 | #include <drm/drm_ioctl.h> |
53 | #include <drm/drm_print.h> | | 53 | #include <drm/drm_print.h> |
54 | | | 54 | |
55 | #include "drm_crtc_internal.h" | | 55 | #include "drm_crtc_internal.h" |
56 | #include "drm_internal.h" | | 56 | #include "drm_internal.h" |
57 | #include "drm_legacy.h" | | 57 | #include "drm_legacy.h" |
58 | | | 58 | |
59 | /** | | 59 | /** |
60 | * DOC: getunique and setversion story | | 60 | * DOC: getunique and setversion story |
61 | * | | 61 | * |
62 | * BEWARE THE DRAGONS! MIND THE TRAPDOORS! | | 62 | * BEWARE THE DRAGONS! MIND THE TRAPDOORS! |
63 | * | | 63 | * |
64 | * In an attempt to warn anyone else who's trying to figure out what's going | | 64 | * In an attempt to warn anyone else who's trying to figure out what's going |
65 | * on here, I'll try to summarize the story. First things first, let's clear up | | 65 | * on here, I'll try to summarize the story. First things first, let's clear up |
66 | * the names, because the kernel internals, libdrm and the ioctls are all named | | 66 | * the names, because the kernel internals, libdrm and the ioctls are all named |
67 | * differently: | | 67 | * differently: |
68 | * | | 68 | * |
69 | * - GET_UNIQUE ioctl, implemented by drm_getunique is wrapped up in libdrm | | 69 | * - GET_UNIQUE ioctl, implemented by drm_getunique is wrapped up in libdrm |
70 | * through the drmGetBusid function. | | 70 | * through the drmGetBusid function. |
71 | * - The libdrm drmSetBusid function is backed by the SET_UNIQUE ioctl. All | | 71 | * - The libdrm drmSetBusid function is backed by the SET_UNIQUE ioctl. All |
72 | * that code is nerved in the kernel with drm_invalid_op(). | | 72 | * that code is nerved in the kernel with drm_invalid_op(). |
73 | * - The internal set_busid kernel functions and driver callbacks are | | 73 | * - The internal set_busid kernel functions and driver callbacks are |
74 | * exclusively use by the SET_VERSION ioctl, because only drm 1.0 (which is | | 74 | * exclusively use by the SET_VERSION ioctl, because only drm 1.0 (which is |
75 | * nerved) allowed userspace to set the busid through the above ioctl. | | 75 | * nerved) allowed userspace to set the busid through the above ioctl. |
76 | * - Other ioctls and functions involved are named consistently. | | 76 | * - Other ioctls and functions involved are named consistently. |
77 | * | | 77 | * |
78 | * For anyone wondering what's the difference between drm 1.1 and 1.4: Correctly | | 78 | * For anyone wondering what's the difference between drm 1.1 and 1.4: Correctly |
79 | * handling pci domains in the busid on ppc. Doing this correctly was only | | 79 | * handling pci domains in the busid on ppc. Doing this correctly was only |
80 | * implemented in libdrm in 2010, hence can't be nerved yet. No one knows what's | | 80 | * implemented in libdrm in 2010, hence can't be nerved yet. No one knows what's |
81 | * special with drm 1.2 and 1.3. | | 81 | * special with drm 1.2 and 1.3. |
82 | * | | 82 | * |
83 | * Now the actual horror story of how device lookup in drm works. At large, | | 83 | * Now the actual horror story of how device lookup in drm works. At large, |
84 | * there's 2 different ways, either by busid, or by device driver name. | | 84 | * there's 2 different ways, either by busid, or by device driver name. |
85 | * | | 85 | * |
86 | * Opening by busid is fairly simple: | | 86 | * Opening by busid is fairly simple: |
87 | * | | 87 | * |
88 | * 1. First call SET_VERSION to make sure pci domains are handled properly. As a | | 88 | * 1. First call SET_VERSION to make sure pci domains are handled properly. As a |
89 | * side-effect this fills out the unique name in the master structure. | | 89 | * side-effect this fills out the unique name in the master structure. |
90 | * 2. Call GET_UNIQUE to read out the unique name from the master structure, | | 90 | * 2. Call GET_UNIQUE to read out the unique name from the master structure, |
91 | * which matches the busid thanks to step 1. If it doesn't, proceed to try | | 91 | * which matches the busid thanks to step 1. If it doesn't, proceed to try |
92 | * the next device node. | | 92 | * the next device node. |
93 | * | | 93 | * |
94 | * Opening by name is slightly different: | | 94 | * Opening by name is slightly different: |
95 | * | | 95 | * |
96 | * 1. Directly call VERSION to get the version and to match against the driver | | 96 | * 1. Directly call VERSION to get the version and to match against the driver |
97 | * name returned by that ioctl. Note that SET_VERSION is not called, which | | 97 | * name returned by that ioctl. Note that SET_VERSION is not called, which |
98 | * means the the unique name for the master node just opening is _not_ filled | | 98 | * means the the unique name for the master node just opening is _not_ filled |
99 | * out. This despite that with current drm device nodes are always bound to | | 99 | * out. This despite that with current drm device nodes are always bound to |
100 | * one device, and can't be runtime assigned like with drm 1.0. | | 100 | * one device, and can't be runtime assigned like with drm 1.0. |
101 | * 2. Match driver name. If it mismatches, proceed to the next device node. | | 101 | * 2. Match driver name. If it mismatches, proceed to the next device node. |
102 | * 3. Call GET_UNIQUE, and check whether the unique name has length zero (by | | 102 | * 3. Call GET_UNIQUE, and check whether the unique name has length zero (by |
103 | * checking that the first byte in the string is 0). If that's not the case | | 103 | * checking that the first byte in the string is 0). If that's not the case |
104 | * libdrm skips and proceeds to the next device node. Probably this is just | | 104 | * libdrm skips and proceeds to the next device node. Probably this is just |
105 | * copypasta from drm 1.0 times where a set unique name meant that the driver | | 105 | * copypasta from drm 1.0 times where a set unique name meant that the driver |
106 | * was in use already, but that's just conjecture. | | 106 | * was in use already, but that's just conjecture. |
107 | * | | 107 | * |
108 | * Long story short: To keep the open by name logic working, GET_UNIQUE must | | 108 | * Long story short: To keep the open by name logic working, GET_UNIQUE must |
109 | * _not_ return a unique string when SET_VERSION hasn't been called yet, | | 109 | * _not_ return a unique string when SET_VERSION hasn't been called yet, |
110 | * otherwise libdrm breaks. Even when that unique string can't ever change, and | | 110 | * otherwise libdrm breaks. Even when that unique string can't ever change, and |
111 | * is totally irrelevant for actually opening the device because runtime | | 111 | * is totally irrelevant for actually opening the device because runtime |
112 | * assignable device instances were only support in drm 1.0, which is long dead. | | 112 | * assignable device instances were only support in drm 1.0, which is long dead. |
113 | * But the libdrm code in drmOpenByName somehow survived, hence this can't be | | 113 | * But the libdrm code in drmOpenByName somehow survived, hence this can't be |
114 | * broken. | | 114 | * broken. |
115 | */ | | 115 | */ |
116 | | | 116 | |
117 | /* | | 117 | /* |
118 | * Get the bus id. | | 118 | * Get the bus id. |
119 | * | | 119 | * |
120 | * \param inode device inode. | | 120 | * \param inode device inode. |
121 | * \param file_priv DRM file private. | | 121 | * \param file_priv DRM file private. |
122 | * \param cmd command. | | 122 | * \param cmd command. |
123 | * \param arg user argument, pointing to a drm_unique structure. | | 123 | * \param arg user argument, pointing to a drm_unique structure. |
124 | * \return zero on success or a negative number on failure. | | 124 | * \return zero on success or a negative number on failure. |
125 | * | | 125 | * |
126 | * Copies the bus id from drm_device::unique into user space. | | 126 | * Copies the bus id from drm_device::unique into user space. |
127 | */ | | 127 | */ |
128 | int drm_getunique(struct drm_device *dev, void *data, | | 128 | int drm_getunique(struct drm_device *dev, void *data, |
129 | struct drm_file *file_priv) | | 129 | struct drm_file *file_priv) |
130 | { | | 130 | { |
131 | struct drm_unique *u = data; | | 131 | struct drm_unique *u = data; |
132 | struct drm_master *master = file_priv->master; | | 132 | struct drm_master *master; |
| | | 133 | int ret; |
133 | | | 134 | |
134 | mutex_lock(&master->dev->master_mutex); | | 135 | mutex_lock(&dev->master_mutex); |
135 | if (u->unique_len >= master->unique_len) { | | 136 | master = dev->master; |
136 | if (copy_to_user(u->unique, master->unique, master->unique_len)) { | | 137 | if (master == NULL) { |
137 | mutex_unlock(&master->dev->master_mutex); | | 138 | ret = -ENXIO; |
138 | return -EFAULT; | | 139 | goto out; |
139 | } | | 140 | } |
| | | 141 | |
| | | 142 | /* |
| | | 143 | * Copy out only if the user allocated enough space. Either |
| | | 144 | * way, on success, report the actual size -- so the user can |
| | | 145 | * allocate enough space if they didn't before, or so they know |
| | | 146 | * exactly how much we copied out. |
| | | 147 | */ |
| | | 148 | if (u->unique_len < master->unique_len) { |
| | | 149 | ret = 0; |
| | | 150 | } else { |
| | | 151 | ret = copy_to_user(u->unique, master->unique, |
| | | 152 | master->unique_len); |
| | | 153 | if (ret) |
| | | 154 | goto out; |
140 | } | | 155 | } |
141 | u->unique_len = master->unique_len; | | 156 | u->unique_len = master->unique_len; |
142 | mutex_unlock(&master->dev->master_mutex); | | | |
143 | | | 157 | |
144 | return 0; | | 158 | out: mutex_unlock(&dev->master_mutex); |
| | | 159 | |
| | | 160 | return ret; |
145 | } | | 161 | } |
146 | | | 162 | |
147 | static void | | 163 | static void |
148 | drm_unset_busid(struct drm_device *dev, | | 164 | drm_unset_busid(struct drm_device *dev, |
149 | struct drm_master *master) | | 165 | struct drm_master *master) |
150 | { | | 166 | { |
151 | kfree(master->unique); | | 167 | kfree(master->unique); |
152 | master->unique = NULL; | | 168 | master->unique = NULL; |
153 | master->unique_len = 0; | | 169 | master->unique_len = 0; |
154 | } | | 170 | } |
155 | | | 171 | |
156 | static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) | | 172 | static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) |
157 | { | | 173 | { |
158 | struct drm_master *master = file_priv->master; | | 174 | struct drm_master *master = file_priv->master; |
159 | int ret; | | 175 | int ret; |
160 | | | 176 | |
161 | if (master->unique != NULL) | | 177 | if (master->unique != NULL) |
162 | drm_unset_busid(dev, master); | | 178 | drm_unset_busid(dev, master); |
163 | | | 179 | |
164 | if (dev->dev && dev_is_pci(dev->dev)) { | | 180 | if (dev->dev && dev_is_pci(dev->dev)) { |
165 | ret = drm_pci_set_busid(dev, master); | | 181 | ret = drm_pci_set_busid(dev, master); |
166 | if (ret) { | | 182 | if (ret) { |
167 | drm_unset_busid(dev, master); | | 183 | drm_unset_busid(dev, master); |
168 | return ret; | | 184 | return ret; |
169 | } | | 185 | } |
170 | } else { | | 186 | } else { |
171 | WARN_ON(!dev->unique); | | 187 | WARN_ON(!dev->unique); |
172 | master->unique = kstrdup(dev->unique, GFP_KERNEL); | | 188 | master->unique = kstrdup(dev->unique, GFP_KERNEL); |
173 | if (master->unique) | | 189 | if (master->unique) |
174 | master->unique_len = strlen(dev->unique); | | 190 | master->unique_len = strlen(dev->unique); |
175 | } | | 191 | } |
176 | | | 192 | |
177 | return 0; | | 193 | return 0; |
178 | } | | 194 | } |
179 | | | 195 | |
180 | /* | | 196 | /* |
181 | * Get client information. | | 197 | * Get client information. |
182 | * | | 198 | * |
183 | * \param inode device inode. | | 199 | * \param inode device inode. |
184 | * \param file_priv DRM file private. | | 200 | * \param file_priv DRM file private. |
185 | * \param cmd command. | | 201 | * \param cmd command. |
186 | * \param arg user argument, pointing to a drm_client structure. | | 202 | * \param arg user argument, pointing to a drm_client structure. |
187 | * | | 203 | * |
188 | * \return zero on success or a negative number on failure. | | 204 | * \return zero on success or a negative number on failure. |
189 | * | | 205 | * |
190 | * Searches for the client with the specified index and copies its information | | 206 | * Searches for the client with the specified index and copies its information |
191 | * into userspace | | 207 | * into userspace |
192 | */ | | 208 | */ |
193 | int drm_getclient(struct drm_device *dev, void *data, | | 209 | int drm_getclient(struct drm_device *dev, void *data, |
194 | struct drm_file *file_priv) | | 210 | struct drm_file *file_priv) |
195 | { | | 211 | { |
196 | struct drm_client *client = data; | | 212 | struct drm_client *client = data; |
197 | | | 213 | |
198 | /* | | 214 | /* |
199 | * Hollowed-out getclient ioctl to keep some dead old drm tests/tools | | 215 | * Hollowed-out getclient ioctl to keep some dead old drm tests/tools |
200 | * not breaking completely. Userspace tools stop enumerating one they | | 216 | * not breaking completely. Userspace tools stop enumerating one they |
201 | * get -EINVAL, hence this is the return value we need to hand back for | | 217 | * get -EINVAL, hence this is the return value we need to hand back for |
202 | * no clients tracked. | | 218 | * no clients tracked. |
203 | * | | 219 | * |
204 | * Unfortunately some clients (*cough* libva *cough*) use this in a fun | | 220 | * Unfortunately some clients (*cough* libva *cough*) use this in a fun |
205 | * attempt to figure out whether they're authenticated or not. Since | | 221 | * attempt to figure out whether they're authenticated or not. Since |
206 | * that's the only thing they care about, give it to the directly | | 222 | * that's the only thing they care about, give it to the directly |
207 | * instead of walking one giant list. | | 223 | * instead of walking one giant list. |
208 | */ | | 224 | */ |
209 | if (client->idx == 0) { | | 225 | if (client->idx == 0) { |
210 | client->auth = file_priv->authenticated; | | 226 | client->auth = file_priv->authenticated; |
211 | #ifdef __NetBSD__ /* XXX Too scary to contemplate. */ | | 227 | #ifdef __NetBSD__ /* XXX Too scary to contemplate. */ |
212 | client->pid = curproc->p_pid; | | 228 | client->pid = curproc->p_pid; |
213 | client->uid = kauth_cred_geteuid(curproc->p_cred); | | 229 | client->uid = kauth_cred_geteuid(curproc->p_cred); |
214 | #else | | 230 | #else |
215 | client->pid = task_pid_vnr(current); | | 231 | client->pid = task_pid_vnr(current); |
216 | client->uid = overflowuid; | | 232 | client->uid = overflowuid; |
217 | #endif | | 233 | #endif |
218 | client->magic = 0; | | 234 | client->magic = 0; |
219 | client->iocs = 0; | | 235 | client->iocs = 0; |
220 | | | 236 | |
221 | return 0; | | 237 | return 0; |
222 | } else { | | 238 | } else { |
223 | return -EINVAL; | | 239 | return -EINVAL; |
224 | } | | 240 | } |
225 | } | | 241 | } |
226 | | | 242 | |
227 | /* | | 243 | /* |
228 | * Get statistics information. | | 244 | * Get statistics information. |
229 | * | | 245 | * |
230 | * \param inode device inode. | | 246 | * \param inode device inode. |
231 | * \param file_priv DRM file private. | | 247 | * \param file_priv DRM file private. |
232 | * \param cmd command. | | 248 | * \param cmd command. |
233 | * \param arg user argument, pointing to a drm_stats structure. | | 249 | * \param arg user argument, pointing to a drm_stats structure. |
234 | * | | 250 | * |
235 | * \return zero on success or a negative number on failure. | | 251 | * \return zero on success or a negative number on failure. |
236 | */ | | 252 | */ |
237 | static int drm_getstats(struct drm_device *dev, void *data, | | 253 | static int drm_getstats(struct drm_device *dev, void *data, |
238 | struct drm_file *file_priv) | | 254 | struct drm_file *file_priv) |
239 | { | | 255 | { |
240 | struct drm_stats *stats = data; | | 256 | struct drm_stats *stats = data; |
241 | | | 257 | |
242 | /* Clear stats to prevent userspace from eating its stack garbage. */ | | 258 | /* Clear stats to prevent userspace from eating its stack garbage. */ |
243 | memset(stats, 0, sizeof(*stats)); | | 259 | memset(stats, 0, sizeof(*stats)); |
244 | | | 260 | |
245 | return 0; | | 261 | return 0; |
246 | } | | 262 | } |
247 | | | 263 | |
248 | /* | | 264 | /* |
249 | * Get device/driver capabilities | | 265 | * Get device/driver capabilities |
250 | */ | | 266 | */ |
251 | static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) | | 267 | static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) |
252 | { | | 268 | { |
253 | struct drm_get_cap *req = data; | | 269 | struct drm_get_cap *req = data; |
254 | struct drm_crtc *crtc; | | 270 | struct drm_crtc *crtc; |
255 | | | 271 | |
256 | req->value = 0; | | 272 | req->value = 0; |
257 | | | 273 | |
258 | /* Only some caps make sense with UMS/render-only drivers. */ | | 274 | /* Only some caps make sense with UMS/render-only drivers. */ |
259 | switch (req->capability) { | | 275 | switch (req->capability) { |
260 | case DRM_CAP_TIMESTAMP_MONOTONIC: | | 276 | case DRM_CAP_TIMESTAMP_MONOTONIC: |
261 | req->value = 1; | | 277 | req->value = 1; |
262 | return 0; | | 278 | return 0; |
263 | case DRM_CAP_PRIME: | | 279 | case DRM_CAP_PRIME: |
264 | req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; | | 280 | req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; |
265 | req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; | | 281 | req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; |
266 | return 0; | | 282 | return 0; |
267 | case DRM_CAP_SYNCOBJ: | | 283 | case DRM_CAP_SYNCOBJ: |
268 | req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ); | | 284 | req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ); |
269 | return 0; | | 285 | return 0; |
270 | case DRM_CAP_SYNCOBJ_TIMELINE: | | 286 | case DRM_CAP_SYNCOBJ_TIMELINE: |
271 | req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE); | | 287 | req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE); |
272 | return 0; | | 288 | return 0; |
273 | } | | 289 | } |
274 | | | 290 | |
275 | /* Other caps only work with KMS drivers */ | | 291 | /* Other caps only work with KMS drivers */ |
276 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | | 292 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
277 | return -EOPNOTSUPP; | | 293 | return -EOPNOTSUPP; |
278 | | | 294 | |
279 | switch (req->capability) { | | 295 | switch (req->capability) { |
280 | case DRM_CAP_DUMB_BUFFER: | | 296 | case DRM_CAP_DUMB_BUFFER: |
281 | if (dev->driver->dumb_create) | | 297 | if (dev->driver->dumb_create) |
282 | req->value = 1; | | 298 | req->value = 1; |
283 | break; | | 299 | break; |
284 | case DRM_CAP_VBLANK_HIGH_CRTC: | | 300 | case DRM_CAP_VBLANK_HIGH_CRTC: |
285 | req->value = 1; | | 301 | req->value = 1; |
286 | break; | | 302 | break; |
287 | case DRM_CAP_DUMB_PREFERRED_DEPTH: | | 303 | case DRM_CAP_DUMB_PREFERRED_DEPTH: |
288 | req->value = dev->mode_config.preferred_depth; | | 304 | req->value = dev->mode_config.preferred_depth; |
289 | break; | | 305 | break; |
290 | case DRM_CAP_DUMB_PREFER_SHADOW: | | 306 | case DRM_CAP_DUMB_PREFER_SHADOW: |
291 | req->value = dev->mode_config.prefer_shadow; | | 307 | req->value = dev->mode_config.prefer_shadow; |
292 | break; | | 308 | break; |
293 | case DRM_CAP_ASYNC_PAGE_FLIP: | | 309 | case DRM_CAP_ASYNC_PAGE_FLIP: |
294 | req->value = dev->mode_config.async_page_flip; | | 310 | req->value = dev->mode_config.async_page_flip; |
295 | break; | | 311 | break; |
296 | case DRM_CAP_PAGE_FLIP_TARGET: | | 312 | case DRM_CAP_PAGE_FLIP_TARGET: |
297 | req->value = 1; | | 313 | req->value = 1; |
298 | drm_for_each_crtc(crtc, dev) { | | 314 | drm_for_each_crtc(crtc, dev) { |
299 | if (!crtc->funcs->page_flip_target) | | 315 | if (!crtc->funcs->page_flip_target) |
300 | req->value = 0; | | 316 | req->value = 0; |
301 | } | | 317 | } |
302 | break; | | 318 | break; |
303 | case DRM_CAP_CURSOR_WIDTH: | | 319 | case DRM_CAP_CURSOR_WIDTH: |
304 | if (dev->mode_config.cursor_width) | | 320 | if (dev->mode_config.cursor_width) |
305 | req->value = dev->mode_config.cursor_width; | | 321 | req->value = dev->mode_config.cursor_width; |
306 | else | | 322 | else |
307 | req->value = 64; | | 323 | req->value = 64; |
308 | break; | | 324 | break; |
309 | case DRM_CAP_CURSOR_HEIGHT: | | 325 | case DRM_CAP_CURSOR_HEIGHT: |
310 | if (dev->mode_config.cursor_height) | | 326 | if (dev->mode_config.cursor_height) |
311 | req->value = dev->mode_config.cursor_height; | | 327 | req->value = dev->mode_config.cursor_height; |
312 | else | | 328 | else |
313 | req->value = 64; | | 329 | req->value = 64; |
314 | break; | | 330 | break; |
315 | case DRM_CAP_ADDFB2_MODIFIERS: | | 331 | case DRM_CAP_ADDFB2_MODIFIERS: |
316 | req->value = dev->mode_config.allow_fb_modifiers; | | 332 | req->value = dev->mode_config.allow_fb_modifiers; |
317 | break; | | 333 | break; |
318 | case DRM_CAP_CRTC_IN_VBLANK_EVENT: | | 334 | case DRM_CAP_CRTC_IN_VBLANK_EVENT: |
319 | req->value = 1; | | 335 | req->value = 1; |
320 | break; | | 336 | break; |
321 | default: | | 337 | default: |
322 | return -EINVAL; | | 338 | return -EINVAL; |
323 | } | | 339 | } |
324 | return 0; | | 340 | return 0; |
325 | } | | 341 | } |
326 | | | 342 | |
327 | /* | | 343 | /* |
328 | * Set device/driver capabilities | | 344 | * Set device/driver capabilities |
329 | */ | | 345 | */ |
330 | static int | | 346 | static int |
331 | drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) | | 347 | drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) |
332 | { | | 348 | { |
333 | struct drm_set_client_cap *req = data; | | 349 | struct drm_set_client_cap *req = data; |
334 | | | 350 | |
335 | /* No render-only settable capabilities for now */ | | 351 | /* No render-only settable capabilities for now */ |
336 | | | 352 | |
337 | /* Below caps that only works with KMS drivers */ | | 353 | /* Below caps that only works with KMS drivers */ |
338 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | | 354 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
339 | return -EOPNOTSUPP; | | 355 | return -EOPNOTSUPP; |
340 | | | 356 | |
341 | switch (req->capability) { | | 357 | switch (req->capability) { |
342 | case DRM_CLIENT_CAP_STEREO_3D: | | 358 | case DRM_CLIENT_CAP_STEREO_3D: |
343 | if (req->value > 1) | | 359 | if (req->value > 1) |
344 | return -EINVAL; | | 360 | return -EINVAL; |
345 | file_priv->stereo_allowed = req->value; | | 361 | file_priv->stereo_allowed = req->value; |
346 | break; | | 362 | break; |
347 | case DRM_CLIENT_CAP_UNIVERSAL_PLANES: | | 363 | case DRM_CLIENT_CAP_UNIVERSAL_PLANES: |
348 | if (req->value > 1) | | 364 | if (req->value > 1) |
349 | return -EINVAL; | | 365 | return -EINVAL; |
350 | file_priv->universal_planes = req->value; | | 366 | file_priv->universal_planes = req->value; |
351 | break; | | 367 | break; |
352 | case DRM_CLIENT_CAP_ATOMIC: | | 368 | case DRM_CLIENT_CAP_ATOMIC: |
353 | if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) | | 369 | if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) |
354 | return -EOPNOTSUPP; | | 370 | return -EOPNOTSUPP; |
355 | /* The modesetting DDX has a totally broken idea of atomic. */ | | 371 | /* The modesetting DDX has a totally broken idea of atomic. */ |
356 | #ifdef __NetBSD__ | | 372 | #ifdef __NetBSD__ |
357 | if (current->p_comm[0] == 'X' && req->value == 1) | | 373 | if (current->p_comm[0] == 'X' && req->value == 1) |
358 | #else | | 374 | #else |
359 | if (current->comm[0] == 'X' && req->value == 1) | | 375 | if (current->comm[0] == 'X' && req->value == 1) |
360 | #endif | | 376 | #endif |
361 | { | | 377 | { |
362 | pr_info("broken atomic modeset userspace detected, disabling atomic\n"); | | 378 | pr_info("broken atomic modeset userspace detected, disabling atomic\n"); |
363 | return -EOPNOTSUPP; | | 379 | return -EOPNOTSUPP; |
364 | } | | 380 | } |
365 | if (req->value > 2) | | 381 | if (req->value > 2) |
366 | return -EINVAL; | | 382 | return -EINVAL; |
367 | file_priv->atomic = req->value; | | 383 | file_priv->atomic = req->value; |
368 | file_priv->universal_planes = req->value; | | 384 | file_priv->universal_planes = req->value; |
369 | /* | | 385 | /* |
370 | * No atomic user-space blows up on aspect ratio mode bits. | | 386 | * No atomic user-space blows up on aspect ratio mode bits. |
371 | */ | | 387 | */ |
372 | file_priv->aspect_ratio_allowed = req->value; | | 388 | file_priv->aspect_ratio_allowed = req->value; |
373 | break; | | 389 | break; |
374 | case DRM_CLIENT_CAP_ASPECT_RATIO: | | 390 | case DRM_CLIENT_CAP_ASPECT_RATIO: |
375 | if (req->value > 1) | | 391 | if (req->value > 1) |
376 | return -EINVAL; | | 392 | return -EINVAL; |
377 | file_priv->aspect_ratio_allowed = req->value; | | 393 | file_priv->aspect_ratio_allowed = req->value; |
378 | break; | | 394 | break; |
379 | case DRM_CLIENT_CAP_WRITEBACK_CONNECTORS: | | 395 | case DRM_CLIENT_CAP_WRITEBACK_CONNECTORS: |
380 | if (!file_priv->atomic) | | 396 | if (!file_priv->atomic) |
381 | return -EINVAL; | | 397 | return -EINVAL; |
382 | if (req->value > 1) | | 398 | if (req->value > 1) |
383 | return -EINVAL; | | 399 | return -EINVAL; |
384 | file_priv->writeback_connectors = req->value; | | 400 | file_priv->writeback_connectors = req->value; |
385 | break; | | 401 | break; |
386 | default: | | 402 | default: |
387 | return -EINVAL; | | 403 | return -EINVAL; |
388 | } | | 404 | } |
389 | | | 405 | |
390 | return 0; | | 406 | return 0; |
391 | } | | 407 | } |
392 | | | 408 | |
393 | /* | | 409 | /* |
394 | * Setversion ioctl. | | 410 | * Setversion ioctl. |
395 | * | | 411 | * |
396 | * \param inode device inode. | | 412 | * \param inode device inode. |
397 | * \param file_priv DRM file private. | | 413 | * \param file_priv DRM file private. |
398 | * \param cmd command. | | 414 | * \param cmd command. |
399 | * \param arg user argument, pointing to a drm_lock structure. | | 415 | * \param arg user argument, pointing to a drm_lock structure. |
400 | * \return zero on success or negative number on failure. | | 416 | * \return zero on success or negative number on failure. |
401 | * | | 417 | * |
402 | * Sets the requested interface version | | 418 | * Sets the requested interface version |
403 | */ | | 419 | */ |
404 | static int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv) | | 420 | static int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv) |
405 | { | | 421 | { |
406 | struct drm_set_version *sv = data; | | 422 | struct drm_set_version *sv = data; |
407 | int if_version, retcode = 0; | | 423 | int if_version, retcode = 0; |
408 | | | 424 | |
409 | mutex_lock(&dev->master_mutex); | | 425 | mutex_lock(&dev->master_mutex); |
410 | if (sv->drm_di_major != -1) { | | 426 | if (sv->drm_di_major != -1) { |
411 | if (sv->drm_di_major != DRM_IF_MAJOR || | | 427 | if (sv->drm_di_major != DRM_IF_MAJOR || |
412 | sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { | | 428 | sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { |
413 | retcode = -EINVAL; | | 429 | retcode = -EINVAL; |
414 | goto done; | | 430 | goto done; |
415 | } | | 431 | } |
416 | if_version = DRM_IF_VERSION(sv->drm_di_major, | | 432 | if_version = DRM_IF_VERSION(sv->drm_di_major, |
417 | sv->drm_di_minor); | | 433 | sv->drm_di_minor); |
418 | dev->if_version = max(if_version, dev->if_version); | | 434 | dev->if_version = max(if_version, dev->if_version); |
419 | if (sv->drm_di_minor >= 1) { | | 435 | if (sv->drm_di_minor >= 1) { |
420 | /* | | 436 | /* |
421 | * Version 1.1 includes tying of DRM to specific device | | 437 | * Version 1.1 includes tying of DRM to specific device |
422 | * Version 1.4 has proper PCI domain support | | 438 | * Version 1.4 has proper PCI domain support |
423 | */ | | 439 | */ |
424 | retcode = drm_set_busid(dev, file_priv); | | 440 | retcode = drm_set_busid(dev, file_priv); |
425 | if (retcode) | | 441 | if (retcode) |
426 | goto done; | | 442 | goto done; |
427 | } | | 443 | } |
428 | } | | 444 | } |
429 | | | 445 | |
430 | if (sv->drm_dd_major != -1) { | | 446 | if (sv->drm_dd_major != -1) { |
431 | if (sv->drm_dd_major != dev->driver->major || | | 447 | if (sv->drm_dd_major != dev->driver->major || |
432 | sv->drm_dd_minor < 0 || sv->drm_dd_minor > | | 448 | sv->drm_dd_minor < 0 || sv->drm_dd_minor > |
433 | dev->driver->minor) { | | 449 | dev->driver->minor) { |
434 | retcode = -EINVAL; | | 450 | retcode = -EINVAL; |
435 | goto done; | | 451 | goto done; |
436 | } | | 452 | } |
437 | } | | 453 | } |
438 | | | 454 | |
439 | done: | | 455 | done: |
440 | sv->drm_di_major = DRM_IF_MAJOR; | | 456 | sv->drm_di_major = DRM_IF_MAJOR; |
441 | sv->drm_di_minor = DRM_IF_MINOR; | | 457 | sv->drm_di_minor = DRM_IF_MINOR; |
442 | sv->drm_dd_major = dev->driver->major; | | 458 | sv->drm_dd_major = dev->driver->major; |
443 | sv->drm_dd_minor = dev->driver->minor; | | 459 | sv->drm_dd_minor = dev->driver->minor; |
444 | mutex_unlock(&dev->master_mutex); | | 460 | mutex_unlock(&dev->master_mutex); |
445 | | | 461 | |
446 | return retcode; | | 462 | return retcode; |
447 | } | | 463 | } |
448 | | | 464 | |
449 | /** | | 465 | /** |
450 | * drm_noop - DRM no-op ioctl implemntation | | 466 | * drm_noop - DRM no-op ioctl implemntation |
451 | * @dev: DRM device for the ioctl | | 467 | * @dev: DRM device for the ioctl |
452 | * @data: data pointer for the ioctl | | 468 | * @data: data pointer for the ioctl |
453 | * @file_priv: DRM file for the ioctl call | | 469 | * @file_priv: DRM file for the ioctl call |
454 | * | | 470 | * |
455 | * This no-op implementation for drm ioctls is useful for deprecated | | 471 | * This no-op implementation for drm ioctls is useful for deprecated |
456 | * functionality where we can't return a failure code because existing userspace | | 472 | * functionality where we can't return a failure code because existing userspace |
457 | * checks the result of the ioctl, but doesn't care about the action. | | 473 | * checks the result of the ioctl, but doesn't care about the action. |
458 | * | | 474 | * |
459 | * Always returns successfully with 0. | | 475 | * Always returns successfully with 0. |
460 | */ | | 476 | */ |
461 | int drm_noop(struct drm_device *dev, void *data, | | 477 | int drm_noop(struct drm_device *dev, void *data, |
462 | struct drm_file *file_priv) | | 478 | struct drm_file *file_priv) |
463 | { | | 479 | { |
464 | DRM_DEBUG("\n"); | | 480 | DRM_DEBUG("\n"); |
465 | return 0; | | 481 | return 0; |
466 | } | | 482 | } |
467 | EXPORT_SYMBOL(drm_noop); | | 483 | EXPORT_SYMBOL(drm_noop); |
468 | | | 484 | |
469 | /** | | 485 | /** |
470 | * drm_invalid_op - DRM invalid ioctl implemntation | | 486 | * drm_invalid_op - DRM invalid ioctl implemntation |
471 | * @dev: DRM device for the ioctl | | 487 | * @dev: DRM device for the ioctl |
472 | * @data: data pointer for the ioctl | | 488 | * @data: data pointer for the ioctl |
473 | * @file_priv: DRM file for the ioctl call | | 489 | * @file_priv: DRM file for the ioctl call |
474 | * | | 490 | * |
475 | * This no-op implementation for drm ioctls is useful for deprecated | | 491 | * This no-op implementation for drm ioctls is useful for deprecated |
476 | * functionality where we really don't want to allow userspace to call the ioctl | | 492 | * functionality where we really don't want to allow userspace to call the ioctl |
477 | * any more. This is the case for old ums interfaces for drivers that | | 493 | * any more. This is the case for old ums interfaces for drivers that |
478 | * transitioned to kms gradually and so kept the old legacy tables around. This | | 494 | * transitioned to kms gradually and so kept the old legacy tables around. This |
479 | * only applies to radeon and i915 kms drivers, other drivers shouldn't need to | | 495 | * only applies to radeon and i915 kms drivers, other drivers shouldn't need to |
480 | * use this function. | | 496 | * use this function. |
481 | * | | 497 | * |
482 | * Always fails with a return value of -EINVAL. | | 498 | * Always fails with a return value of -EINVAL. |
483 | */ | | 499 | */ |
484 | int drm_invalid_op(struct drm_device *dev, void *data, | | 500 | int drm_invalid_op(struct drm_device *dev, void *data, |
485 | struct drm_file *file_priv) | | 501 | struct drm_file *file_priv) |
486 | { | | 502 | { |
487 | return -EINVAL; | | 503 | return -EINVAL; |
488 | } | | 504 | } |
489 | EXPORT_SYMBOL(drm_invalid_op); | | 505 | EXPORT_SYMBOL(drm_invalid_op); |
490 | | | 506 | |
491 | /* | | 507 | /* |
492 | * Copy and IOCTL return string to user space | | 508 | * Copy and IOCTL return string to user space |
493 | */ | | 509 | */ |
494 | static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) | | 510 | static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) |
495 | { | | 511 | { |
496 | int len; | | 512 | int len; |
497 | | | 513 | |
498 | /* don't overflow userbuf */ | | 514 | /* don't overflow userbuf */ |
499 | len = strlen(value); | | 515 | len = strlen(value); |
500 | if (len > *buf_len) | | 516 | if (len > *buf_len) |
501 | len = *buf_len; | | 517 | len = *buf_len; |
502 | | | 518 | |
503 | /* let userspace know exact length of driver value (which could be | | 519 | /* let userspace know exact length of driver value (which could be |
504 | * larger than the userspace-supplied buffer) */ | | 520 | * larger than the userspace-supplied buffer) */ |
505 | *buf_len = strlen(value); | | 521 | *buf_len = strlen(value); |
506 | | | 522 | |
507 | /* finally, try filling in the userbuf */ | | 523 | /* finally, try filling in the userbuf */ |
508 | if (len && buf) | | 524 | if (len && buf) |
509 | if (copy_to_user(buf, value, len)) | | 525 | if (copy_to_user(buf, value, len)) |
510 | return -EFAULT; | | 526 | return -EFAULT; |
511 | return 0; | | 527 | return 0; |
512 | } | | 528 | } |
513 | | | 529 | |
514 | /* | | 530 | /* |
515 | * Get version information | | 531 | * Get version information |
516 | * | | 532 | * |
517 | * \param inode device inode. | | 533 | * \param inode device inode. |
518 | * \param filp file pointer. | | 534 | * \param filp file pointer. |
519 | * \param cmd command. | | 535 | * \param cmd command. |
520 | * \param arg user argument, pointing to a drm_version structure. | | 536 | * \param arg user argument, pointing to a drm_version structure. |
521 | * \return zero on success or negative number on failure. | | 537 | * \return zero on success or negative number on failure. |
522 | * | | 538 | * |
523 | * Fills in the version information in \p arg. | | 539 | * Fills in the version information in \p arg. |
524 | */ | | 540 | */ |
525 | int drm_version(struct drm_device *dev, void *data, | | 541 | int drm_version(struct drm_device *dev, void *data, |
526 | struct drm_file *file_priv) | | 542 | struct drm_file *file_priv) |
527 | { | | 543 | { |
528 | struct drm_version *version = data; | | 544 | struct drm_version *version = data; |
529 | int err; | | 545 | int err; |
530 | | | 546 | |
531 | version->version_major = dev->driver->major; | | 547 | version->version_major = dev->driver->major; |
532 | version->version_minor = dev->driver->minor; | | 548 | version->version_minor = dev->driver->minor; |
533 | version->version_patchlevel = dev->driver->patchlevel; | | 549 | version->version_patchlevel = dev->driver->patchlevel; |
534 | err = drm_copy_field(version->name, &version->name_len, | | 550 | err = drm_copy_field(version->name, &version->name_len, |
535 | dev->driver->name); | | 551 | dev->driver->name); |
536 | if (!err) | | 552 | if (!err) |
537 | err = drm_copy_field(version->date, &version->date_len, | | 553 | err = drm_copy_field(version->date, &version->date_len, |
538 | dev->driver->date); | | 554 | dev->driver->date); |
539 | if (!err) | | 555 | if (!err) |
540 | err = drm_copy_field(version->desc, &version->desc_len, | | 556 | err = drm_copy_field(version->desc, &version->desc_len, |
541 | dev->driver->desc); | | 557 | dev->driver->desc); |
542 | | | 558 | |
543 | return err; | | 559 | return err; |
544 | } | | 560 | } |
545 | | | 561 | |
546 | /** | | 562 | /** |
547 | * drm_ioctl_permit - Check ioctl permissions against caller | | 563 | * drm_ioctl_permit - Check ioctl permissions against caller |
548 | * | | 564 | * |
549 | * @flags: ioctl permission flags. | | 565 | * @flags: ioctl permission flags. |
550 | * @file_priv: Pointer to struct drm_file identifying the caller. | | 566 | * @file_priv: Pointer to struct drm_file identifying the caller. |
551 | * | | 567 | * |
552 | * Checks whether the caller is allowed to run an ioctl with the | | 568 | * Checks whether the caller is allowed to run an ioctl with the |
553 | * indicated permissions. | | 569 | * indicated permissions. |
554 | * | | 570 | * |
555 | * Returns: | | 571 | * Returns: |
556 | * Zero if allowed, -EACCES otherwise. | | 572 | * Zero if allowed, -EACCES otherwise. |
557 | */ | | 573 | */ |
558 | int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) | | 574 | int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) |
559 | { | | 575 | { |
560 | /* ROOT_ONLY is only for CAP_SYS_ADMIN */ | | 576 | /* ROOT_ONLY is only for CAP_SYS_ADMIN */ |
561 | if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN))) | | 577 | if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN))) |
562 | return -EACCES; | | 578 | return -EACCES; |
563 | | | 579 | |
564 | /* AUTH is only for authenticated or render client */ | | 580 | /* AUTH is only for authenticated or render client */ |
565 | if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) && | | 581 | if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) && |
566 | !file_priv->authenticated)) | | 582 | !file_priv->authenticated)) |
567 | return -EACCES; | | 583 | return -EACCES; |
568 | | | 584 | |
569 | /* MASTER is only for master or control clients */ | | 585 | /* MASTER is only for master or control clients */ |
570 | if (unlikely((flags & DRM_MASTER) && | | 586 | if (unlikely((flags & DRM_MASTER) && |
571 | !drm_is_current_master(file_priv))) | | 587 | !drm_is_current_master(file_priv))) |
572 | return -EACCES; | | 588 | return -EACCES; |
573 | | | 589 | |
574 | /* Render clients must be explicitly allowed */ | | 590 | /* Render clients must be explicitly allowed */ |
575 | if (unlikely(!(flags & DRM_RENDER_ALLOW) && | | 591 | if (unlikely(!(flags & DRM_RENDER_ALLOW) && |
576 | drm_is_render_client(file_priv))) | | 592 | drm_is_render_client(file_priv))) |
577 | return -EACCES; | | 593 | return -EACCES; |
578 | | | 594 | |
579 | return 0; | | 595 | return 0; |
580 | } | | 596 | } |
581 | EXPORT_SYMBOL(drm_ioctl_permit); | | 597 | EXPORT_SYMBOL(drm_ioctl_permit); |
582 | | | 598 | |
583 | #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ | | 599 | #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ |
584 | [DRM_IOCTL_NR(ioctl)] = { \ | | 600 | [DRM_IOCTL_NR(ioctl)] = { \ |
585 | .cmd = ioctl, \ | | 601 | .cmd = ioctl, \ |
586 | .func = _func, \ | | 602 | .func = _func, \ |
587 | .flags = _flags, \ | | 603 | .flags = _flags, \ |
588 | .name = #ioctl \ | | 604 | .name = #ioctl \ |
589 | } | | 605 | } |
590 | | | 606 | |
591 | #if IS_ENABLED(CONFIG_DRM_LEGACY) | | 607 | #if IS_ENABLED(CONFIG_DRM_LEGACY) |
592 | #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, _func, _flags) | | 608 | #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, _func, _flags) |
593 | #else | | 609 | #else |
594 | #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, drm_invalid_op, _flags) | | 610 | #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, drm_invalid_op, _flags) |
595 | #endif | | 611 | #endif |
596 | | | 612 | |
597 | /* Ioctl table */ | | 613 | /* Ioctl table */ |
598 | static const struct drm_ioctl_desc drm_ioctls[] = { | | 614 | static const struct drm_ioctl_desc drm_ioctls[] = { |
599 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW), | | 615 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW), |
600 | DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), | | 616 | DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, DRM_RENDER_ALLOW), |
601 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), | | 617 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), |
602 | DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), | | 618 | DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), |
603 | | | 619 | |
604 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0), | | 620 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0), |
605 | | | 621 | |
606 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), | | 622 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), |
607 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), | | 623 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), |
608 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW), | | 624 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW), |
609 | DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), | | 625 | DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), |
610 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), | | 626 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), |
611 | | | 627 | |
612 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 628 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
613 | DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 629 | DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
614 | DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 630 | DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
615 | DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_MASTER), | | 631 | DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_MASTER), |
616 | | | 632 | |
617 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 633 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
618 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH), | | 634 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH), |
619 | | | 635 | |
620 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 636 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
621 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH), | | 637 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH), |
622 | | | 638 | |
623 | DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), | | 639 | DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), |
624 | DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), | | 640 | DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), |
625 | | | 641 | |
626 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY), | | 642 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY), |
627 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 643 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
628 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 644 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
629 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH), | | 645 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH), |
630 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 646 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
631 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 647 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
632 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH), | | 648 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH), |
633 | | | 649 | |
634 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 650 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
635 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 651 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
636 | | | 652 | |
637 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_LOCK, drm_legacy_lock, DRM_AUTH), | | 653 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_LOCK, drm_legacy_lock, DRM_AUTH), |
638 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_legacy_unlock, DRM_AUTH), | | 654 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_legacy_unlock, DRM_AUTH), |
639 | | | 655 | |
640 | DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), | | 656 | DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), |
641 | | | 657 | |
642 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_legacy_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 658 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_legacy_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
643 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_legacy_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 659 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_legacy_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
644 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_legacy_infobufs, DRM_AUTH), | | 660 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_legacy_infobufs, DRM_AUTH), |
645 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_legacy_mapbufs, DRM_AUTH), | | 661 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_legacy_mapbufs, DRM_AUTH), |
646 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_legacy_freebufs, DRM_AUTH), | | 662 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_legacy_freebufs, DRM_AUTH), |
647 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_DMA, drm_legacy_dma_ioctl, DRM_AUTH), | | 663 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_DMA, drm_legacy_dma_ioctl, DRM_AUTH), |
648 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_legacy_irq_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 664 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_legacy_irq_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
649 | | | 665 | |
650 | #if IS_ENABLED(CONFIG_AGP) | | 666 | #if IS_ENABLED(CONFIG_AGP) |
651 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 667 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
652 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 668 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
653 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 669 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
654 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), | | 670 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), |
655 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 671 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
656 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 672 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
657 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 673 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
658 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 674 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
659 | #endif | | 675 | #endif |
660 | | | 676 | |
661 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 677 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
662 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 678 | DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
663 | | | 679 | |
664 | DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, DRM_UNLOCKED), | | 680 | DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, DRM_UNLOCKED), |
665 | | | 681 | |
666 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl_ioctl, 0), | | 682 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl_ioctl, 0), |
667 | | | 683 | |
668 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 684 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
669 | | | 685 | |
670 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW), | | 686 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW), |
671 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), | | 687 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), |
672 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), | | 688 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), |
673 | | | 689 | |
674 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0), | | 690 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0), |
675 | | | 691 | |
676 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_RENDER_ALLOW), | | 692 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_RENDER_ALLOW), |
677 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_RENDER_ALLOW), | | 693 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_RENDER_ALLOW), |
678 | | | 694 | |
679 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, 0), | | 695 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, 0), |
680 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, 0), | | 696 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, 0), |
681 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER), | | 697 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER), |
682 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, 0), | | 698 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, 0), |
683 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER), | | 699 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER), |
684 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER), | | 700 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER), |
685 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, 0), | | 701 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, 0), |
686 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), | | 702 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), |
687 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, 0), | | 703 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, 0), |
688 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, 0), | | 704 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, 0), |
689 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER), | | 705 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER), |
690 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER), | | 706 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER), |
691 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, 0), | | 707 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, 0), |
692 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER), | | 708 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER), |
693 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, 0), | | 709 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, 0), |
694 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, 0), | | 710 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, 0), |
695 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0), | | 711 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0), |
696 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0), | | 712 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0), |
697 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0), | | 713 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0), |
698 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER), | | 714 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER), |
699 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER), | | 715 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER), |
700 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0), | | 716 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0), |
701 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0), | | 717 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0), |
702 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0), | | 718 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0), |
703 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0), | | 719 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0), |
704 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER), | | 720 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER), |
705 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER), | | 721 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER), |
706 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER), | | 722 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER), |
707 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, 0), | | 723 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, 0), |
708 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, 0), | | 724 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, 0), |
709 | | | 725 | |
710 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_CREATE, drm_syncobj_create_ioctl, | | 726 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_CREATE, drm_syncobj_create_ioctl, |
711 | DRM_RENDER_ALLOW), | | 727 | DRM_RENDER_ALLOW), |
712 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_DESTROY, drm_syncobj_destroy_ioctl, | | 728 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_DESTROY, drm_syncobj_destroy_ioctl, |
713 | DRM_RENDER_ALLOW), | | 729 | DRM_RENDER_ALLOW), |
714 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, drm_syncobj_handle_to_fd_ioctl, | | 730 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, drm_syncobj_handle_to_fd_ioctl, |
715 | DRM_RENDER_ALLOW), | | 731 | DRM_RENDER_ALLOW), |
716 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, | | 732 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, |
717 | DRM_RENDER_ALLOW), | | 733 | DRM_RENDER_ALLOW), |
718 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TRANSFER, drm_syncobj_transfer_ioctl, | | 734 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TRANSFER, drm_syncobj_transfer_ioctl, |
719 | DRM_RENDER_ALLOW), | | 735 | DRM_RENDER_ALLOW), |
720 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, | | 736 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, |
721 | DRM_RENDER_ALLOW), | | 737 | DRM_RENDER_ALLOW), |
722 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl, | | 738 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl, |
723 | DRM_RENDER_ALLOW), | | 739 | DRM_RENDER_ALLOW), |
724 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl, | | 740 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl, |
725 | DRM_RENDER_ALLOW), | | 741 | DRM_RENDER_ALLOW), |
726 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, | | 742 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, |
727 | DRM_RENDER_ALLOW), | | 743 | DRM_RENDER_ALLOW), |
728 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl, | | 744 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl, |
729 | DRM_RENDER_ALLOW), | | 745 | DRM_RENDER_ALLOW), |
730 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl, | | 746 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl, |
731 | DRM_RENDER_ALLOW), | | 747 | DRM_RENDER_ALLOW), |
732 | DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, 0), | | 748 | DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, 0), |
733 | DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, 0), | | 749 | DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, 0), |
734 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER), | | 750 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER), |
735 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER), | | 751 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER), |
736 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER), | | 752 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER), |
737 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER), | | 753 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER), |
738 | }; | | 754 | }; |
739 | | | 755 | |
740 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | | 756 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
741 | | | 757 | |
742 | #ifdef __NetBSD__ | | 758 | #ifdef __NetBSD__ |
743 | /* ioctl suspend/resume */ | | 759 | /* ioctl suspend/resume */ |
744 | | | 760 | |
745 | static void | | 761 | static void |
746 | drm_ioctl_enter(struct drm_device *dev) | | 762 | drm_ioctl_enter(struct drm_device *dev) |
747 | { | | 763 | { |
748 | int ret __diagused; | | 764 | int ret __diagused; |
749 | | | 765 | |
750 | mutex_lock(&dev->suspend_lock); | | 766 | mutex_lock(&dev->suspend_lock); |
751 | DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock, | | 767 | DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock, |
752 | dev->suspender == NULL); | | 768 | dev->suspender == NULL); |
753 | KASSERTMSG(ret == 0, "error=%d", -ret); | | 769 | KASSERTMSG(ret == 0, "error=%d", -ret); |
754 | dev->active_ioctls++; | | 770 | dev->active_ioctls++; |
755 | mutex_unlock(&dev->suspend_lock); | | 771 | mutex_unlock(&dev->suspend_lock); |
756 | } | | 772 | } |
757 | | | 773 | |
758 | static void | | 774 | static void |
759 | drm_ioctl_exit(struct drm_device *dev) | | 775 | drm_ioctl_exit(struct drm_device *dev) |
760 | { | | 776 | { |
761 | | | 777 | |
762 | mutex_lock(&dev->suspend_lock); | | 778 | mutex_lock(&dev->suspend_lock); |
763 | KASSERT(dev->suspender == NULL); | | 779 | KASSERT(dev->suspender == NULL); |
764 | if (--dev->active_ioctls == 0) | | 780 | if (--dev->active_ioctls == 0) |
765 | DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock); | | 781 | DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock); |
766 | mutex_unlock(&dev->suspend_lock); | | 782 | mutex_unlock(&dev->suspend_lock); |
767 | } | | 783 | } |
768 | | | 784 | |
769 | void | | 785 | void |
770 | drm_suspend_ioctl(struct drm_device *dev) | | 786 | drm_suspend_ioctl(struct drm_device *dev) |
771 | { | | 787 | { |
772 | int ret; | | 788 | int ret; |
773 | | | 789 | |
774 | mutex_lock(&dev->suspend_lock); | | 790 | mutex_lock(&dev->suspend_lock); |
775 | DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock, | | 791 | DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock, |
776 | dev->suspender == NULL && dev->active_ioctls == 0); | | 792 | dev->suspender == NULL && dev->active_ioctls == 0); |
777 | dev->suspender = curlwp; | | 793 | dev->suspender = curlwp; |
778 | mutex_unlock(&dev->suspend_lock); | | 794 | mutex_unlock(&dev->suspend_lock); |
779 | } | | 795 | } |
780 | | | 796 | |
781 | void | | 797 | void |
782 | drm_resume_ioctl(struct drm_device *dev) | | 798 | drm_resume_ioctl(struct drm_device *dev) |
783 | { | | 799 | { |
784 | | | 800 | |
785 | mutex_lock(&dev->suspend_lock); | | 801 | mutex_lock(&dev->suspend_lock); |
786 | KASSERT(dev->suspender); | | 802 | KASSERT(dev->suspender); |
787 | KASSERT(dev->active_ioctls == 0); | | 803 | KASSERT(dev->active_ioctls == 0); |
788 | dev->suspender = NULL; | | 804 | dev->suspender = NULL; |
789 | DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock); | | 805 | DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock); |
790 | mutex_unlock(&dev->suspend_lock); | | 806 | mutex_unlock(&dev->suspend_lock); |
791 | } | | 807 | } |
792 | #endif | | 808 | #endif |
793 | | | 809 | |
794 | /** | | 810 | /** |
795 | * DOC: driver specific ioctls | | 811 | * DOC: driver specific ioctls |
796 | * | | 812 | * |
797 | * First things first, driver private IOCTLs should only be needed for drivers | | 813 | * First things first, driver private IOCTLs should only be needed for drivers |
798 | * supporting rendering. Kernel modesetting is all standardized, and extended | | 814 | * supporting rendering. Kernel modesetting is all standardized, and extended |
799 | * through properties. There are a few exceptions in some existing drivers, | | 815 | * through properties. There are a few exceptions in some existing drivers, |
800 | * which define IOCTL for use by the display DRM master, but they all predate | | 816 | * which define IOCTL for use by the display DRM master, but they all predate |
801 | * properties. | | 817 | * properties. |
802 | * | | 818 | * |
803 | * Now if you do have a render driver you always have to support it through | | 819 | * Now if you do have a render driver you always have to support it through |
804 | * driver private properties. There's a few steps needed to wire all the things | | 820 | * driver private properties. There's a few steps needed to wire all the things |
805 | * up. | | 821 | * up. |
806 | * | | 822 | * |
807 | * First you need to define the structure for your IOCTL in your driver private | | 823 | * First you need to define the structure for your IOCTL in your driver private |
808 | * UAPI header in ``include/uapi/drm/my_driver_drm.h``:: | | 824 | * UAPI header in ``include/uapi/drm/my_driver_drm.h``:: |
809 | * | | 825 | * |
810 | * struct my_driver_operation { | | 826 | * struct my_driver_operation { |
811 | * u32 some_thing; | | 827 | * u32 some_thing; |
812 | * u32 another_thing; | | 828 | * u32 another_thing; |
813 | * }; | | 829 | * }; |
814 | * | | 830 | * |
815 | * Please make sure that you follow all the best practices from | | 831 | * Please make sure that you follow all the best practices from |
816 | * ``Documentation/ioctl/botching-up-ioctls.rst``. Note that drm_ioctl() | | 832 | * ``Documentation/ioctl/botching-up-ioctls.rst``. Note that drm_ioctl() |
817 | * automatically zero-extends structures, hence make sure you can add more stuff | | 833 | * automatically zero-extends structures, hence make sure you can add more stuff |
818 | * at the end, i.e. don't put a variable sized array there. | | 834 | * at the end, i.e. don't put a variable sized array there. |
819 | * | | 835 | * |
820 | * Then you need to define your IOCTL number, using one of DRM_IO(), DRM_IOR(), | | 836 | * Then you need to define your IOCTL number, using one of DRM_IO(), DRM_IOR(), |
821 | * DRM_IOW() or DRM_IOWR(). It must start with the DRM_IOCTL\_ prefix:: | | 837 | * DRM_IOW() or DRM_IOWR(). It must start with the DRM_IOCTL\_ prefix:: |
822 | * | | 838 | * |
823 | * ##define DRM_IOCTL_MY_DRIVER_OPERATION \ | | 839 | * ##define DRM_IOCTL_MY_DRIVER_OPERATION \ |
824 | * DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation) | | 840 | * DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation) |
825 | * | | 841 | * |
826 | * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to | | 842 | * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to |
827 | * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire | | 843 | * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire |
828 | * up the handlers and set the access rights:: | | 844 | * up the handlers and set the access rights:: |
829 | * | | 845 | * |
830 | * static const struct drm_ioctl_desc my_driver_ioctls[] = { | | 846 | * static const struct drm_ioctl_desc my_driver_ioctls[] = { |
831 | * DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation, | | 847 | * DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation, |
832 | * DRM_AUTH|DRM_RENDER_ALLOW), | | 848 | * DRM_AUTH|DRM_RENDER_ALLOW), |
833 | * }; | | 849 | * }; |
834 | * | | 850 | * |
835 | * And then assign this to the &drm_driver.ioctls field in your driver | | 851 | * And then assign this to the &drm_driver.ioctls field in your driver |
836 | * structure. | | 852 | * structure. |
837 | * | | 853 | * |
838 | * See the separate chapter on :ref:`file operations<drm_driver_fops>` for how | | 854 | * See the separate chapter on :ref:`file operations<drm_driver_fops>` for how |
839 | * the driver-specific IOCTLs are wired up. | | 855 | * the driver-specific IOCTLs are wired up. |
840 | */ | | 856 | */ |
841 | | | 857 | |
842 | long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata, | | 858 | long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata, |
843 | u32 flags) | | 859 | u32 flags) |
844 | { | | 860 | { |
845 | #ifdef __NetBSD__ | | 861 | #ifdef __NetBSD__ |
846 | struct drm_file *file_priv = file->f_data; | | 862 | struct drm_file *file_priv = file->f_data; |
847 | #else | | 863 | #else |
848 | struct drm_file *file_priv = file->private_data; | | 864 | struct drm_file *file_priv = file->private_data; |
849 | #endif | | 865 | #endif |
850 | struct drm_device *dev = file_priv->minor->dev; | | 866 | struct drm_device *dev = file_priv->minor->dev; |
851 | int retcode; | | 867 | int retcode; |
852 | | | 868 | |
853 | if (drm_dev_is_unplugged(dev)) | | 869 | if (drm_dev_is_unplugged(dev)) |
854 | return -ENODEV; | | 870 | return -ENODEV; |
855 | | | 871 | |
856 | retcode = drm_ioctl_permit(flags, file_priv); | | 872 | retcode = drm_ioctl_permit(flags, file_priv); |
857 | if (unlikely(retcode)) | | 873 | if (unlikely(retcode)) |
858 | return retcode; | | 874 | return retcode; |
859 | | | 875 | |
860 | drm_ioctl_enter(dev); | | 876 | drm_ioctl_enter(dev); |
861 | | | 877 | |
862 | /* Enforce sane locking for modern driver ioctls. */ | | 878 | /* Enforce sane locking for modern driver ioctls. */ |
863 | if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) || | | 879 | if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) || |
864 | (flags & DRM_UNLOCKED)) | | 880 | (flags & DRM_UNLOCKED)) |
865 | retcode = func(dev, kdata, file_priv); | | 881 | retcode = func(dev, kdata, file_priv); |
866 | else { | | 882 | else { |
867 | mutex_lock(&drm_global_mutex); | | 883 | mutex_lock(&drm_global_mutex); |
868 | retcode = func(dev, kdata, file_priv); | | 884 | retcode = func(dev, kdata, file_priv); |
869 | mutex_unlock(&drm_global_mutex); | | 885 | mutex_unlock(&drm_global_mutex); |
870 | } | | 886 | } |
871 | | | 887 | |
872 | drm_ioctl_exit(dev); | | 888 | drm_ioctl_exit(dev); |
873 | | | 889 | |
874 | return retcode; | | 890 | return retcode; |
875 | } | | 891 | } |
876 | EXPORT_SYMBOL(drm_ioctl_kernel); | | 892 | EXPORT_SYMBOL(drm_ioctl_kernel); |
877 | | | 893 | |
878 | /** | | 894 | /** |
879 | * drm_ioctl - ioctl callback implementation for DRM drivers | | 895 | * drm_ioctl - ioctl callback implementation for DRM drivers |
880 | * @filp: file this ioctl is called on | | 896 | * @filp: file this ioctl is called on |
881 | * @cmd: ioctl cmd number | | 897 | * @cmd: ioctl cmd number |
882 | * @arg: user argument | | 898 | * @arg: user argument |
883 | * | | 899 | * |
884 | * Looks up the ioctl function in the DRM core and the driver dispatch table, | | 900 | * Looks up the ioctl function in the DRM core and the driver dispatch table, |
885 | * stored in &drm_driver.ioctls. It checks for necessary permission by calling | | 901 | * stored in &drm_driver.ioctls. It checks for necessary permission by calling |
886 | * drm_ioctl_permit(), and dispatches to the respective function. | | 902 | * drm_ioctl_permit(), and dispatches to the respective function. |
887 | * | | 903 | * |
888 | * Returns: | | 904 | * Returns: |
889 | * Zero on success, negative error code on failure. | | 905 | * Zero on success, negative error code on failure. |
890 | */ | | 906 | */ |
891 | #ifdef __NetBSD__ | | 907 | #ifdef __NetBSD__ |
892 | #include <sys/file.h> | | 908 | #include <sys/file.h> |
893 | int | | 909 | int |
894 | drm_ioctl(struct file *fp, unsigned long cmd, void *data) | | 910 | drm_ioctl(struct file *fp, unsigned long cmd, void *data) |
895 | { | | 911 | { |
896 | char stackbuf[128] __aligned(ALIGNBYTES + 1); | | 912 | char stackbuf[128] __aligned(ALIGNBYTES + 1); |
897 | char *buf = stackbuf; | | 913 | char *buf = stackbuf; |
898 | void *data0 = data; | | 914 | void *data0 = data; |
899 | struct drm_file *const file = fp->f_data; | | 915 | struct drm_file *const file = fp->f_data; |
900 | const unsigned int nr = DRM_IOCTL_NR(cmd); | | 916 | const unsigned int nr = DRM_IOCTL_NR(cmd); |
901 | int error; | | 917 | int error; |
902 | | | 918 | |
903 | switch (cmd) { | | 919 | switch (cmd) { |
904 | case FIONBIO: | | 920 | case FIONBIO: |
905 | case FIOASYNC: | | 921 | case FIOASYNC: |
906 | return 0; | | 922 | return 0; |
907 | default: | | 923 | default: |
908 | break; | | 924 | break; |
909 | } | | 925 | } |
910 | | | 926 | |
911 | if (IOCGROUP(cmd) != DRM_IOCTL_BASE) | | 927 | if (IOCGROUP(cmd) != DRM_IOCTL_BASE) |
912 | return EINVAL; | | 928 | return EINVAL; |
913 | | | 929 | |
914 | KASSERT(file != NULL); | | 930 | KASSERT(file != NULL); |
915 | KASSERT(file->minor != NULL); | | 931 | KASSERT(file->minor != NULL); |
916 | KASSERT(file->minor->dev != NULL); | | 932 | KASSERT(file->minor->dev != NULL); |
917 | struct drm_device *const dev = file->minor->dev; | | 933 | struct drm_device *const dev = file->minor->dev; |
918 | const struct drm_ioctl_desc *ioctl; | | 934 | const struct drm_ioctl_desc *ioctl; |
919 | | | 935 | |
920 | if (drm_dev_is_unplugged(dev)) | | 936 | if (drm_dev_is_unplugged(dev)) |
921 | return ENXIO; | | 937 | return ENXIO; |
922 | | | 938 | |
923 | const bool is_driver_ioctl = | | 939 | const bool is_driver_ioctl = |
924 | (DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END); | | 940 | (DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END); |
925 | | | 941 | |
926 | if (is_driver_ioctl) { | | 942 | if (is_driver_ioctl) { |
927 | const unsigned int driver_nr = nr - DRM_COMMAND_BASE; | | 943 | const unsigned int driver_nr = nr - DRM_COMMAND_BASE; |
928 | if (driver_nr >= dev->driver->num_ioctls) | | 944 | if (driver_nr >= dev->driver->num_ioctls) |
929 | return EINVAL; | | 945 | return EINVAL; |
930 | ioctl = &dev->driver->ioctls[driver_nr]; | | 946 | ioctl = &dev->driver->ioctls[driver_nr]; |
931 | } else if (nr < __arraycount(drm_ioctls)) { | | 947 | } else if (nr < __arraycount(drm_ioctls)) { |
932 | ioctl = &drm_ioctls[nr]; | | 948 | ioctl = &drm_ioctls[nr]; |
933 | } else { | | 949 | } else { |
934 | ioctl = NULL; | | 950 | ioctl = NULL; |
935 | } | | 951 | } |
936 | | | 952 | |
937 | if ((ioctl == NULL) || (ioctl->func == NULL)) | | 953 | if ((ioctl == NULL) || (ioctl->func == NULL)) |
938 | return EINVAL; | | 954 | return EINVAL; |
939 | | | 955 | |
940 | /* XXX errno Linux->NetBSD */ | | 956 | /* XXX errno Linux->NetBSD */ |
941 | error = -drm_ioctl_permit(ioctl->flags, file); | | 957 | error = -drm_ioctl_permit(ioctl->flags, file); |
942 | if (error) | | 958 | if (error) |
943 | return error; | | 959 | return error; |
944 | | | 960 | |
945 | /* If userland passed in too few bytes, zero-pad them. */ | | 961 | /* If userland passed in too few bytes, zero-pad them. */ |
946 | if (IOCPARM_LEN(cmd) < IOCPARM_LEN(ioctl->cmd)) { | | 962 | if (IOCPARM_LEN(cmd) < IOCPARM_LEN(ioctl->cmd)) { |
947 | /* 12-bit quantity, according to <sys/ioccom.h> */ | | 963 | /* 12-bit quantity, according to <sys/ioccom.h> */ |
948 | KASSERT(IOCPARM_LEN(ioctl->cmd) <= 4096); | | 964 | KASSERT(IOCPARM_LEN(ioctl->cmd) <= 4096); |
949 | if (IOCPARM_LEN(ioctl->cmd) > sizeof stackbuf) { | | 965 | if (IOCPARM_LEN(ioctl->cmd) > sizeof stackbuf) { |
950 | buf = kmem_alloc(IOCPARM_LEN(ioctl->cmd), KM_NOSLEEP); | | 966 | buf = kmem_alloc(IOCPARM_LEN(ioctl->cmd), KM_NOSLEEP); |
951 | if (buf == NULL) | | 967 | if (buf == NULL) |
952 | return ENOMEM; | | 968 | return ENOMEM; |
953 | } | | 969 | } |
954 | memcpy(buf, data, IOCPARM_LEN(cmd)); | | 970 | memcpy(buf, data, IOCPARM_LEN(cmd)); |
955 | memset(buf + IOCPARM_LEN(cmd), 0, | | 971 | memset(buf + IOCPARM_LEN(cmd), 0, |
956 | IOCPARM_LEN(ioctl->cmd) - IOCPARM_LEN(cmd)); | | 972 | IOCPARM_LEN(ioctl->cmd) - IOCPARM_LEN(cmd)); |
957 | data0 = buf; | | 973 | data0 = buf; |
958 | } | | 974 | } |
959 | | | 975 | |
960 | drm_ioctl_enter(dev); | | 976 | drm_ioctl_enter(dev); |
961 | if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) || | | 977 | if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) || |
962 | ISSET(ioctl->flags, DRM_UNLOCKED)) { | | 978 | ISSET(ioctl->flags, DRM_UNLOCKED)) { |
963 | /* XXX errno Linux->NetBSD */ | | 979 | /* XXX errno Linux->NetBSD */ |
964 | error = -(*ioctl->func)(dev, data0, file); | | 980 | error = -(*ioctl->func)(dev, data0, file); |
965 | } else { | | 981 | } else { |
966 | mutex_lock(&drm_global_mutex); | | 982 | mutex_lock(&drm_global_mutex); |
967 | /* XXX errno Linux->NetBSD */ | | 983 | /* XXX errno Linux->NetBSD */ |
968 | error = -(*ioctl->func)(dev, data0, file); | | 984 | error = -(*ioctl->func)(dev, data0, file); |
969 | mutex_unlock(&drm_global_mutex); | | 985 | mutex_unlock(&drm_global_mutex); |
970 | } | | 986 | } |
971 | drm_ioctl_exit(dev); | | 987 | drm_ioctl_exit(dev); |
972 | | | 988 | |
973 | /* If we used a temporary buffer, copy it back out. */ | | 989 | /* If we used a temporary buffer, copy it back out. */ |
974 | if (data != data0) | | 990 | if (data != data0) |
975 | memcpy(data, data0, IOCPARM_LEN(cmd)); | | 991 | memcpy(data, data0, IOCPARM_LEN(cmd)); |
976 | | | 992 | |
977 | /* If we had to allocate a heap buffer, free it. */ | | 993 | /* If we had to allocate a heap buffer, free it. */ |
978 | if (buf != stackbuf) | | 994 | if (buf != stackbuf) |
979 | kmem_free(buf, IOCPARM_LEN(ioctl->cmd)); | | 995 | kmem_free(buf, IOCPARM_LEN(ioctl->cmd)); |
980 | | | 996 | |
981 | return error; | | 997 | return error; |
982 | } | | 998 | } |
983 | #else | | 999 | #else |
984 | long drm_ioctl(struct file *filp, | | 1000 | long drm_ioctl(struct file *filp, |
985 | unsigned int cmd, unsigned long arg) | | 1001 | unsigned int cmd, unsigned long arg) |
986 | { | | 1002 | { |
987 | struct drm_file *file_priv = filp->private_data; | | 1003 | struct drm_file *file_priv = filp->private_data; |
988 | struct drm_device *dev; | | 1004 | struct drm_device *dev; |
989 | const struct drm_ioctl_desc *ioctl = NULL; | | 1005 | const struct drm_ioctl_desc *ioctl = NULL; |
990 | drm_ioctl_t *func; | | 1006 | drm_ioctl_t *func; |
991 | unsigned int nr = DRM_IOCTL_NR(cmd); | | 1007 | unsigned int nr = DRM_IOCTL_NR(cmd); |
992 | int retcode = -EINVAL; | | 1008 | int retcode = -EINVAL; |
993 | char stack_kdata[128]; | | 1009 | char stack_kdata[128]; |
994 | char *kdata = NULL; | | 1010 | char *kdata = NULL; |
995 | unsigned int in_size, out_size, drv_size, ksize; | | 1011 | unsigned int in_size, out_size, drv_size, ksize; |
996 | bool is_driver_ioctl; | | 1012 | bool is_driver_ioctl; |
997 | | | 1013 | |
998 | dev = file_priv->minor->dev; | | 1014 | dev = file_priv->minor->dev; |
999 | | | 1015 | |
1000 | if (drm_dev_is_unplugged(dev)) | | 1016 | if (drm_dev_is_unplugged(dev)) |
1001 | return -ENODEV; | | 1017 | return -ENODEV; |
1002 | | | 1018 | |
1003 | is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END; | | 1019 | is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END; |
1004 | | | 1020 | |
1005 | if (is_driver_ioctl) { | | 1021 | if (is_driver_ioctl) { |
1006 | /* driver ioctl */ | | 1022 | /* driver ioctl */ |
1007 | unsigned int index = nr - DRM_COMMAND_BASE; | | 1023 | unsigned int index = nr - DRM_COMMAND_BASE; |
1008 | | | 1024 | |
1009 | if (index >= dev->driver->num_ioctls) | | 1025 | if (index >= dev->driver->num_ioctls) |
1010 | goto err_i1; | | 1026 | goto err_i1; |
1011 | index = array_index_nospec(index, dev->driver->num_ioctls); | | 1027 | index = array_index_nospec(index, dev->driver->num_ioctls); |
1012 | ioctl = &dev->driver->ioctls[index]; | | 1028 | ioctl = &dev->driver->ioctls[index]; |
1013 | } else { | | 1029 | } else { |
1014 | /* core ioctl */ | | 1030 | /* core ioctl */ |
1015 | if (nr >= DRM_CORE_IOCTL_COUNT) | | 1031 | if (nr >= DRM_CORE_IOCTL_COUNT) |
1016 | goto err_i1; | | 1032 | goto err_i1; |
1017 | nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT); | | 1033 | nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT); |
1018 | ioctl = &drm_ioctls[nr]; | | 1034 | ioctl = &drm_ioctls[nr]; |
1019 | } | | 1035 | } |
1020 | | | 1036 | |
1021 | drv_size = _IOC_SIZE(ioctl->cmd); | | 1037 | drv_size = _IOC_SIZE(ioctl->cmd); |
1022 | out_size = in_size = _IOC_SIZE(cmd); | | 1038 | out_size = in_size = _IOC_SIZE(cmd); |
1023 | if ((cmd & ioctl->cmd & IOC_IN) == 0) | | 1039 | if ((cmd & ioctl->cmd & IOC_IN) == 0) |
1024 | in_size = 0; | | 1040 | in_size = 0; |
1025 | if ((cmd & ioctl->cmd & IOC_OUT) == 0) | | 1041 | if ((cmd & ioctl->cmd & IOC_OUT) == 0) |
1026 | out_size = 0; | | 1042 | out_size = 0; |
1027 | ksize = max(max(in_size, out_size), drv_size); | | 1043 | ksize = max(max(in_size, out_size), drv_size); |
1028 | | | 1044 | |
1029 | DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", | | 1045 | DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", |
1030 | task_pid_nr(current), | | 1046 | task_pid_nr(current), |
1031 | (long)old_encode_dev(file_priv->minor->kdev->devt), | | 1047 | (long)old_encode_dev(file_priv->minor->kdev->devt), |
1032 | file_priv->authenticated, ioctl->name); | | 1048 | file_priv->authenticated, ioctl->name); |
1033 | | | 1049 | |
1034 | /* Do not trust userspace, use our own definition */ | | 1050 | /* Do not trust userspace, use our own definition */ |
1035 | func = ioctl->func; | | 1051 | func = ioctl->func; |
1036 | | | 1052 | |
1037 | if (unlikely(!func)) { | | 1053 | if (unlikely(!func)) { |
1038 | DRM_DEBUG("no function\n"); | | 1054 | DRM_DEBUG("no function\n"); |
1039 | retcode = -EINVAL; | | 1055 | retcode = -EINVAL; |
1040 | goto err_i1; | | 1056 | goto err_i1; |
1041 | } | | 1057 | } |
1042 | | | 1058 | |
1043 | if (ksize <= sizeof(stack_kdata)) { | | 1059 | if (ksize <= sizeof(stack_kdata)) { |
1044 | kdata = stack_kdata; | | 1060 | kdata = stack_kdata; |
1045 | } else { | | 1061 | } else { |
1046 | kdata = kmalloc(ksize, GFP_KERNEL); | | 1062 | kdata = kmalloc(ksize, GFP_KERNEL); |
1047 | if (!kdata) { | | 1063 | if (!kdata) { |
1048 | retcode = -ENOMEM; | | 1064 | retcode = -ENOMEM; |
1049 | goto err_i1; | | 1065 | goto err_i1; |
1050 | } | | 1066 | } |
1051 | } | | 1067 | } |
1052 | | | 1068 | |
1053 | if (copy_from_user(kdata, (void __user *)arg, in_size) != 0) { | | 1069 | if (copy_from_user(kdata, (void __user *)arg, in_size) != 0) { |
1054 | retcode = -EFAULT; | | 1070 | retcode = -EFAULT; |
1055 | goto err_i1; | | 1071 | goto err_i1; |
1056 | } | | 1072 | } |
1057 | | | 1073 | |
1058 | if (ksize > in_size) | | 1074 | if (ksize > in_size) |
1059 | memset(kdata + in_size, 0, ksize - in_size); | | 1075 | memset(kdata + in_size, 0, ksize - in_size); |
1060 | | | 1076 | |
1061 | retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags); | | 1077 | retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags); |
1062 | if (copy_to_user((void __user *)arg, kdata, out_size) != 0) | | 1078 | if (copy_to_user((void __user *)arg, kdata, out_size) != 0) |
1063 | retcode = -EFAULT; | | 1079 | retcode = -EFAULT; |
1064 | | | 1080 | |
1065 | err_i1: | | 1081 | err_i1: |
1066 | if (!ioctl) | | 1082 | if (!ioctl) |
1067 | DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", | | 1083 | DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", |
1068 | task_pid_nr(current), | | 1084 | task_pid_nr(current), |
1069 | (long)old_encode_dev(file_priv->minor->kdev->devt), | | 1085 | (long)old_encode_dev(file_priv->minor->kdev->devt), |
1070 | file_priv->authenticated, cmd, nr); | | 1086 | file_priv->authenticated, cmd, nr); |
1071 | | | 1087 | |
1072 | if (kdata != stack_kdata) | | 1088 | if (kdata != stack_kdata) |
1073 | kfree(kdata); | | 1089 | kfree(kdata); |
1074 | if (retcode) | | 1090 | if (retcode) |
1075 | DRM_DEBUG("pid=%d, ret = %d\n", task_pid_nr(current), retcode); | | 1091 | DRM_DEBUG("pid=%d, ret = %d\n", task_pid_nr(current), retcode); |
1076 | return retcode; | | 1092 | return retcode; |
1077 | } | | 1093 | } |
1078 | #endif | | 1094 | #endif |
1079 | EXPORT_SYMBOL(drm_ioctl); | | 1095 | EXPORT_SYMBOL(drm_ioctl); |
1080 | | | 1096 | |
1081 | /** | | 1097 | /** |
1082 | * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags | | 1098 | * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags |
1083 | * @nr: ioctl number | | 1099 | * @nr: ioctl number |
1084 | * @flags: where to return the ioctl permission flags | | 1100 | * @flags: where to return the ioctl permission flags |
1085 | * | | 1101 | * |
1086 | * This ioctl is only used by the vmwgfx driver to augment the access checks | | 1102 | * This ioctl is only used by the vmwgfx driver to augment the access checks |
1087 | * done by the drm core and insofar a pretty decent layering violation. This | | 1103 | * done by the drm core and insofar a pretty decent layering violation. This |
1088 | * shouldn't be used by any drivers. | | 1104 | * shouldn't be used by any drivers. |
1089 | * | | 1105 | * |
1090 | * Returns: | | 1106 | * Returns: |
1091 | * True if the @nr corresponds to a DRM core ioctl number, false otherwise. | | 1107 | * True if the @nr corresponds to a DRM core ioctl number, false otherwise. |
1092 | */ | | 1108 | */ |
1093 | bool drm_ioctl_flags(unsigned int nr, unsigned int *flags) | | 1109 | bool drm_ioctl_flags(unsigned int nr, unsigned int *flags) |
1094 | { | | 1110 | { |
1095 | if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) | | 1111 | if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) |
1096 | return false; | | 1112 | return false; |
1097 | | | 1113 | |
1098 | if (nr >= DRM_CORE_IOCTL_COUNT) | | 1114 | if (nr >= DRM_CORE_IOCTL_COUNT) |
1099 | return false; | | 1115 | return false; |
1100 | nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT); | | 1116 | nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT); |
1101 | | | 1117 | |
1102 | *flags = drm_ioctls[nr].flags; | | 1118 | *flags = drm_ioctls[nr].flags; |
1103 | return true; | | 1119 | return true; |
1104 | } | | 1120 | } |
1105 | EXPORT_SYMBOL(drm_ioctl_flags); | | 1121 | EXPORT_SYMBOL(drm_ioctl_flags); |