1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <drm/drmP.h>
37#include <drm/drm_core.h>
38
39#include <linux/pci.h>
40#include <linux/export.h>
41#ifdef CONFIG_X86
42#include <asm/mtrr.h>
43#endif
44
45
46
47
48
49
50
51
52
53
54
55
56int drm_getunique(struct drm_device *dev, void *data,
57 struct drm_file *file_priv)
58{
59 struct drm_unique *u = data;
60 struct drm_master *master = file_priv->master;
61
62 if (u->unique_len >= master->unique_len) {
63 if (copy_to_user(u->unique, master->unique, master->unique_len))
64 return -EFAULT;
65 }
66 u->unique_len = master->unique_len;
67
68 return 0;
69}
70
71static void
72drm_unset_busid(struct drm_device *dev,
73 struct drm_master *master)
74{
75 kfree(master->unique);
76 master->unique = NULL;
77 master->unique_len = 0;
78 master->unique_size = 0;
79}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96int drm_setunique(struct drm_device *dev, void *data,
97 struct drm_file *file_priv)
98{
99 struct drm_unique *u = data;
100 struct drm_master *master = file_priv->master;
101 int ret;
102
103 if (master->unique_len || master->unique)
104 return -EBUSY;
105
106 if (!u->unique_len || u->unique_len > 1024)
107 return -EINVAL;
108
109 if (drm_core_check_feature(dev, DRIVER_MODESET))
110 return 0;
111
112 if (WARN_ON(!dev->pdev))
113 return -EINVAL;
114
115 ret = drm_pci_set_unique(dev, master, u);
116 if (ret)
117 goto err;
118
119 return 0;
120
121err:
122 drm_unset_busid(dev, master);
123 return ret;
124}
125
126static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
127{
128 struct drm_master *master = file_priv->master;
129 int ret;
130
131 if (master->unique != NULL)
132 drm_unset_busid(dev, master);
133
134 if (dev->driver->bus && dev->driver->bus->set_busid) {
135 ret = dev->driver->bus->set_busid(dev, master);
136 if (ret) {
137 drm_unset_busid(dev, master);
138 return ret;
139 }
140 } else {
141 if (WARN(dev->unique == NULL,
142 "No drm_bus.set_busid() implementation provided by "
143 "%ps. Use drm_dev_set_unique() to set the unique "
144 "name explicitly.", dev->driver))
145 return -EINVAL;
146
147 master->unique = kstrdup(dev->unique, GFP_KERNEL);
148 if (master->unique)
149 master->unique_len = strlen(dev->unique);
150 }
151
152 return 0;
153}
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168int drm_getmap(struct drm_device *dev, void *data,
169 struct drm_file *file_priv)
170{
171 struct drm_map *map = data;
172 struct drm_map_list *r_list = NULL;
173 struct list_head *list;
174 int idx;
175 int i;
176
177 idx = map->offset;
178 if (idx < 0)
179 return -EINVAL;
180
181 i = 0;
182 mutex_lock(&dev->struct_mutex);
183 list_for_each(list, &dev->maplist) {
184 if (i == idx) {
185 r_list = list_entry(list, struct drm_map_list, head);
186 break;
187 }
188 i++;
189 }
190 if (!r_list || !r_list->map) {
191 mutex_unlock(&dev->struct_mutex);
192 return -EINVAL;
193 }
194
195 map->offset = r_list->map->offset;
196 map->size = r_list->map->size;
197 map->type = r_list->map->type;
198 map->flags = r_list->map->flags;
199 map->handle = (void *)(unsigned long) r_list->user_token;
200
201#ifdef CONFIG_X86
202
203
204
205
206 map->mtrr = phys_wc_to_mtrr_index(r_list->map->mtrr);
207#else
208 map->mtrr = -1;
209#endif
210
211 mutex_unlock(&dev->struct_mutex);
212
213 return 0;
214}
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229int drm_getclient(struct drm_device *dev, void *data,
230 struct drm_file *file_priv)
231{
232 struct drm_client *client = data;
233
234
235
236
237
238
239
240
241
242
243
244
245 if (client->idx == 0) {
246 client->auth = file_priv->authenticated;
247 client->pid = pid_vnr(file_priv->pid);
248 client->uid = from_kuid_munged(current_user_ns(),
249 file_priv->uid);
250 client->magic = 0;
251 client->iocs = 0;
252
253 return 0;
254 } else {
255 return -EINVAL;
256 }
257}
258
259
260
261
262
263
264
265
266
267
268
269int drm_getstats(struct drm_device *dev, void *data,
270 struct drm_file *file_priv)
271{
272 struct drm_stats *stats = data;
273
274
275 memset(stats, 0, sizeof(*stats));
276
277 return 0;
278}
279
280
281
282
283int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
284{
285 struct drm_get_cap *req = data;
286
287 req->value = 0;
288 switch (req->capability) {
289 case DRM_CAP_DUMB_BUFFER:
290 if (dev->driver->dumb_create)
291 req->value = 1;
292 break;
293 case DRM_CAP_VBLANK_HIGH_CRTC:
294 req->value = 1;
295 break;
296 case DRM_CAP_DUMB_PREFERRED_DEPTH:
297 req->value = dev->mode_config.preferred_depth;
298 break;
299 case DRM_CAP_DUMB_PREFER_SHADOW:
300 req->value = dev->mode_config.prefer_shadow;
301 break;
302 case DRM_CAP_PRIME:
303 req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
304 req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
305 break;
306 case DRM_CAP_TIMESTAMP_MONOTONIC:
307 req->value = drm_timestamp_monotonic;
308 break;
309 case DRM_CAP_ASYNC_PAGE_FLIP:
310 req->value = dev->mode_config.async_page_flip;
311 break;
312 case DRM_CAP_CURSOR_WIDTH:
313 if (dev->mode_config.cursor_width)
314 req->value = dev->mode_config.cursor_width;
315 else
316 req->value = 64;
317 break;
318 case DRM_CAP_CURSOR_HEIGHT:
319 if (dev->mode_config.cursor_height)
320 req->value = dev->mode_config.cursor_height;
321 else
322 req->value = 64;
323 break;
324 default:
325 return -EINVAL;
326 }
327 return 0;
328}
329
330
331
332
333int
334drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
335{
336 struct drm_set_client_cap *req = data;
337
338 switch (req->capability) {
339 case DRM_CLIENT_CAP_STEREO_3D:
340 if (req->value > 1)
341 return -EINVAL;
342 file_priv->stereo_allowed = req->value;
343 break;
344 case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
345 if (!drm_universal_planes)
346 return -EINVAL;
347 if (req->value > 1)
348 return -EINVAL;
349 file_priv->universal_planes = req->value;
350 break;
351 default:
352 return -EINVAL;
353 }
354
355 return 0;
356}
357
358
359
360
361
362
363
364
365
366
367
368
369int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
370{
371 struct drm_set_version *sv = data;
372 int if_version, retcode = 0;
373
374 if (sv->drm_di_major != -1) {
375 if (sv->drm_di_major != DRM_IF_MAJOR ||
376 sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
377 retcode = -EINVAL;
378 goto done;
379 }
380 if_version = DRM_IF_VERSION(sv->drm_di_major,
381 sv->drm_di_minor);
382 dev->if_version = max(if_version, dev->if_version);
383 if (sv->drm_di_minor >= 1) {
384
385
386
387
388 retcode = drm_set_busid(dev, file_priv);
389 if (retcode)
390 goto done;
391 }
392 }
393
394 if (sv->drm_dd_major != -1) {
395 if (sv->drm_dd_major != dev->driver->major ||
396 sv->drm_dd_minor < 0 || sv->drm_dd_minor >
397 dev->driver->minor) {
398 retcode = -EINVAL;
399 goto done;
400 }
401 }
402
403done:
404 sv->drm_di_major = DRM_IF_MAJOR;
405 sv->drm_di_minor = DRM_IF_MINOR;
406 sv->drm_dd_major = dev->driver->major;
407 sv->drm_dd_minor = dev->driver->minor;
408
409 return retcode;
410}
411
412
413int drm_noop(struct drm_device *dev, void *data,
414 struct drm_file *file_priv)
415{
416 DRM_DEBUG("\n");
417 return 0;
418}
419EXPORT_SYMBOL(drm_noop);
420