1 | /* |
2 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
3 | * \author Daryll Strauss <daryll@valinux.com> |
4 | * \author Gareth Hughes <gareth@valinux.com> |
5 | */ |
6 | |
7 | /* |
8 | * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com |
9 | * |
10 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
11 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
12 | * All Rights Reserved. |
13 | * |
14 | * Permission is hereby granted, free of charge, to any person obtaining a |
15 | * copy of this software and associated documentation files (the "Software"), |
16 | * to deal in the Software without restriction, including without limitation |
17 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
18 | * and/or sell copies of the Software, and to permit persons to whom the |
19 | * Software is furnished to do so, subject to the following conditions: |
20 | * |
21 | * The above copyright notice and this permission notice (including the next |
22 | * paragraph) shall be included in all copies or substantial portions of the |
23 | * Software. |
24 | * |
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
26 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
27 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
28 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
29 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
30 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
31 | * OTHER DEALINGS IN THE SOFTWARE. |
32 | */ |
33 | |
34 | #include <linux/anon_inodes.h> |
35 | #include <linux/dma-fence.h> |
36 | #include <linux/file.h> |
37 | #include <linux/module.h> |
38 | #include <linux/pci.h> |
39 | #include <linux/poll.h> |
40 | #include <linux/slab.h> |
41 | |
42 | #include <drm/drm_client.h> |
43 | #include <drm/drm_drv.h> |
44 | #include <drm/drm_file.h> |
45 | #include <drm/drm_gem.h> |
46 | #include <drm/drm_print.h> |
47 | |
48 | #include "drm_crtc_internal.h" |
49 | #include "drm_internal.h" |
50 | #include "drm_legacy.h" |
51 | |
52 | /* from BKL pushdown */ |
53 | DEFINE_MUTEX(drm_global_mutex); |
54 | |
55 | bool drm_dev_needs_global_mutex(struct drm_device *dev) |
56 | { |
57 | /* |
58 | * Legacy drivers rely on all kinds of BKL locking semantics, don't |
59 | * bother. They also still need BKL locking for their ioctls, so better |
60 | * safe than sorry. |
61 | */ |
62 | if (drm_core_check_feature(dev, feature: DRIVER_LEGACY)) |
63 | return true; |
64 | |
65 | /* |
66 | * The deprecated ->load callback must be called after the driver is |
67 | * already registered. This means such drivers rely on the BKL to make |
68 | * sure an open can't proceed until the driver is actually fully set up. |
69 | * Similar hilarity holds for the unload callback. |
70 | */ |
71 | if (dev->driver->load || dev->driver->unload) |
72 | return true; |
73 | |
74 | /* |
75 | * Drivers with the lastclose callback assume that it's synchronized |
76 | * against concurrent opens, which again needs the BKL. The proper fix |
77 | * is to use the drm_client infrastructure with proper locking for each |
78 | * client. |
79 | */ |
80 | if (dev->driver->lastclose) |
81 | return true; |
82 | |
83 | return false; |
84 | } |
85 | |
86 | /** |
87 | * DOC: file operations |
88 | * |
89 | * Drivers must define the file operations structure that forms the DRM |
90 | * userspace API entry point, even though most of those operations are |
91 | * implemented in the DRM core. The resulting &struct file_operations must be |
92 | * stored in the &drm_driver.fops field. The mandatory functions are drm_open(), |
93 | * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled |
94 | * Note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n, so there's no |
95 | * need to sprinkle #ifdef into the code. Drivers which implement private ioctls |
96 | * that require 32/64 bit compatibility support must provide their own |
97 | * &file_operations.compat_ioctl handler that processes private ioctls and calls |
98 | * drm_compat_ioctl() for core ioctls. |
99 | * |
100 | * In addition drm_read() and drm_poll() provide support for DRM events. DRM |
101 | * events are a generic and extensible means to send asynchronous events to |
102 | * userspace through the file descriptor. They are used to send vblank event and |
103 | * page flip completions by the KMS API. But drivers can also use it for their |
104 | * own needs, e.g. to signal completion of rendering. |
105 | * |
106 | * For the driver-side event interface see drm_event_reserve_init() and |
107 | * drm_send_event() as the main starting points. |
108 | * |
109 | * The memory mapping implementation will vary depending on how the driver |
110 | * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap() |
111 | * function, modern drivers should use one of the provided memory-manager |
112 | * specific implementations. For GEM-based drivers this is drm_gem_mmap(). |
113 | * |
114 | * No other file operations are supported by the DRM userspace API. Overall the |
115 | * following is an example &file_operations structure:: |
116 | * |
117 | * static const example_drm_fops = { |
118 | * .owner = THIS_MODULE, |
119 | * .open = drm_open, |
120 | * .release = drm_release, |
121 | * .unlocked_ioctl = drm_ioctl, |
122 | * .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n |
123 | * .poll = drm_poll, |
124 | * .read = drm_read, |
125 | * .llseek = no_llseek, |
126 | * .mmap = drm_gem_mmap, |
127 | * }; |
128 | * |
129 | * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for |
130 | * DMA based drivers there is the DEFINE_DRM_GEM_DMA_FOPS() macro to make this |
131 | * simpler. |
132 | * |
133 | * The driver's &file_operations must be stored in &drm_driver.fops. |
134 | * |
135 | * For driver-private IOCTL handling see the more detailed discussion in |
136 | * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`. |
137 | */ |
138 | |
139 | /** |
140 | * drm_file_alloc - allocate file context |
141 | * @minor: minor to allocate on |
142 | * |
143 | * This allocates a new DRM file context. It is not linked into any context and |
144 | * can be used by the caller freely. Note that the context keeps a pointer to |
145 | * @minor, so it must be freed before @minor is. |
146 | * |
147 | * RETURNS: |
148 | * Pointer to newly allocated context, ERR_PTR on failure. |
149 | */ |
150 | struct drm_file *drm_file_alloc(struct drm_minor *minor) |
151 | { |
152 | static atomic64_t ident = ATOMIC_INIT(0); |
153 | struct drm_device *dev = minor->dev; |
154 | struct drm_file *file; |
155 | int ret; |
156 | |
157 | file = kzalloc(size: sizeof(*file), GFP_KERNEL); |
158 | if (!file) |
159 | return ERR_PTR(error: -ENOMEM); |
160 | |
161 | /* Get a unique identifier for fdinfo: */ |
162 | file->client_id = atomic64_inc_return(v: &ident); |
163 | rcu_assign_pointer(file->pid, get_pid(task_tgid(current))); |
164 | file->minor = minor; |
165 | |
166 | /* for compatibility root is always authenticated */ |
167 | file->authenticated = capable(CAP_SYS_ADMIN); |
168 | |
169 | INIT_LIST_HEAD(list: &file->lhead); |
170 | INIT_LIST_HEAD(list: &file->fbs); |
171 | mutex_init(&file->fbs_lock); |
172 | INIT_LIST_HEAD(list: &file->blobs); |
173 | INIT_LIST_HEAD(list: &file->pending_event_list); |
174 | INIT_LIST_HEAD(list: &file->event_list); |
175 | init_waitqueue_head(&file->event_wait); |
176 | file->event_space = 4096; /* set aside 4k for event buffer */ |
177 | |
178 | spin_lock_init(&file->master_lookup_lock); |
179 | mutex_init(&file->event_read_lock); |
180 | |
181 | if (drm_core_check_feature(dev, feature: DRIVER_GEM)) |
182 | drm_gem_open(dev, file_private: file); |
183 | |
184 | if (drm_core_check_feature(dev, feature: DRIVER_SYNCOBJ)) |
185 | drm_syncobj_open(file_private: file); |
186 | |
187 | drm_prime_init_file_private(prime_fpriv: &file->prime); |
188 | |
189 | if (dev->driver->open) { |
190 | ret = dev->driver->open(dev, file); |
191 | if (ret < 0) |
192 | goto out_prime_destroy; |
193 | } |
194 | |
195 | return file; |
196 | |
197 | out_prime_destroy: |
198 | drm_prime_destroy_file_private(prime_fpriv: &file->prime); |
199 | if (drm_core_check_feature(dev, feature: DRIVER_SYNCOBJ)) |
200 | drm_syncobj_release(file_private: file); |
201 | if (drm_core_check_feature(dev, feature: DRIVER_GEM)) |
202 | drm_gem_release(dev, file_private: file); |
203 | put_pid(rcu_access_pointer(file->pid)); |
204 | kfree(objp: file); |
205 | |
206 | return ERR_PTR(error: ret); |
207 | } |
208 | |
209 | static void drm_events_release(struct drm_file *file_priv) |
210 | { |
211 | struct drm_device *dev = file_priv->minor->dev; |
212 | struct drm_pending_event *e, *et; |
213 | unsigned long flags; |
214 | |
215 | spin_lock_irqsave(&dev->event_lock, flags); |
216 | |
217 | /* Unlink pending events */ |
218 | list_for_each_entry_safe(e, et, &file_priv->pending_event_list, |
219 | pending_link) { |
220 | list_del(entry: &e->pending_link); |
221 | e->file_priv = NULL; |
222 | } |
223 | |
224 | /* Remove unconsumed events */ |
225 | list_for_each_entry_safe(e, et, &file_priv->event_list, link) { |
226 | list_del(entry: &e->link); |
227 | kfree(objp: e); |
228 | } |
229 | |
230 | spin_unlock_irqrestore(lock: &dev->event_lock, flags); |
231 | } |
232 | |
233 | /** |
234 | * drm_file_free - free file context |
235 | * @file: context to free, or NULL |
236 | * |
237 | * This destroys and deallocates a DRM file context previously allocated via |
238 | * drm_file_alloc(). The caller must make sure to unlink it from any contexts |
239 | * before calling this. |
240 | * |
241 | * If NULL is passed, this is a no-op. |
242 | */ |
243 | void drm_file_free(struct drm_file *file) |
244 | { |
245 | struct drm_device *dev; |
246 | |
247 | if (!file) |
248 | return; |
249 | |
250 | dev = file->minor->dev; |
251 | |
252 | drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n" , |
253 | current->comm, task_pid_nr(current), |
254 | (long)old_encode_dev(file->minor->kdev->devt), |
255 | atomic_read(&dev->open_count)); |
256 | |
257 | #ifdef CONFIG_DRM_LEGACY |
258 | if (drm_core_check_feature(dev, feature: DRIVER_LEGACY) && |
259 | dev->driver->preclose) |
260 | dev->driver->preclose(dev, file); |
261 | #endif |
262 | |
263 | if (drm_core_check_feature(dev, feature: DRIVER_LEGACY)) |
264 | drm_legacy_lock_release(dev, filp: file->filp); |
265 | |
266 | if (drm_core_check_feature(dev, feature: DRIVER_HAVE_DMA)) |
267 | drm_legacy_reclaim_buffers(dev, filp: file); |
268 | |
269 | drm_events_release(file_priv: file); |
270 | |
271 | if (drm_core_check_feature(dev, feature: DRIVER_MODESET)) { |
272 | drm_fb_release(file_priv: file); |
273 | drm_property_destroy_user_blobs(dev, file_priv: file); |
274 | } |
275 | |
276 | if (drm_core_check_feature(dev, feature: DRIVER_SYNCOBJ)) |
277 | drm_syncobj_release(file_private: file); |
278 | |
279 | if (drm_core_check_feature(dev, feature: DRIVER_GEM)) |
280 | drm_gem_release(dev, file_private: file); |
281 | |
282 | drm_legacy_ctxbitmap_flush(dev, file); |
283 | |
284 | if (drm_is_primary_client(file_priv: file)) |
285 | drm_master_release(file_priv: file); |
286 | |
287 | if (dev->driver->postclose) |
288 | dev->driver->postclose(dev, file); |
289 | |
290 | drm_prime_destroy_file_private(prime_fpriv: &file->prime); |
291 | |
292 | WARN_ON(!list_empty(&file->event_list)); |
293 | |
294 | put_pid(rcu_access_pointer(file->pid)); |
295 | kfree(objp: file); |
296 | } |
297 | |
298 | static void drm_close_helper(struct file *filp) |
299 | { |
300 | struct drm_file *file_priv = filp->private_data; |
301 | struct drm_device *dev = file_priv->minor->dev; |
302 | |
303 | mutex_lock(&dev->filelist_mutex); |
304 | list_del(entry: &file_priv->lhead); |
305 | mutex_unlock(lock: &dev->filelist_mutex); |
306 | |
307 | drm_file_free(file: file_priv); |
308 | } |
309 | |
310 | /* |
311 | * Check whether DRI will run on this CPU. |
312 | * |
313 | * \return non-zero if the DRI will run on this CPU, or zero otherwise. |
314 | */ |
315 | static int drm_cpu_valid(void) |
316 | { |
317 | #if defined(__sparc__) && !defined(__sparc_v9__) |
318 | return 0; /* No cmpxchg before v9 sparc. */ |
319 | #endif |
320 | return 1; |
321 | } |
322 | |
323 | /* |
324 | * Called whenever a process opens a drm node |
325 | * |
326 | * \param filp file pointer. |
327 | * \param minor acquired minor-object. |
328 | * \return zero on success or a negative number on failure. |
329 | * |
330 | * Creates and initializes a drm_file structure for the file private data in \p |
331 | * filp and add it into the double linked list in \p dev. |
332 | */ |
333 | int drm_open_helper(struct file *filp, struct drm_minor *minor) |
334 | { |
335 | struct drm_device *dev = minor->dev; |
336 | struct drm_file *priv; |
337 | int ret; |
338 | |
339 | if (filp->f_flags & O_EXCL) |
340 | return -EBUSY; /* No exclusive opens */ |
341 | if (!drm_cpu_valid()) |
342 | return -EINVAL; |
343 | if (dev->switch_power_state != DRM_SWITCH_POWER_ON && |
344 | dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) |
345 | return -EINVAL; |
346 | |
347 | drm_dbg_core(dev, "comm=\"%s\", pid=%d, minor=%d\n" , |
348 | current->comm, task_pid_nr(current), minor->index); |
349 | |
350 | priv = drm_file_alloc(minor); |
351 | if (IS_ERR(ptr: priv)) |
352 | return PTR_ERR(ptr: priv); |
353 | |
354 | if (drm_is_primary_client(file_priv: priv)) { |
355 | ret = drm_master_open(file_priv: priv); |
356 | if (ret) { |
357 | drm_file_free(file: priv); |
358 | return ret; |
359 | } |
360 | } |
361 | |
362 | filp->private_data = priv; |
363 | filp->f_mode |= FMODE_UNSIGNED_OFFSET; |
364 | priv->filp = filp; |
365 | |
366 | mutex_lock(&dev->filelist_mutex); |
367 | list_add(new: &priv->lhead, head: &dev->filelist); |
368 | mutex_unlock(lock: &dev->filelist_mutex); |
369 | |
370 | #ifdef CONFIG_DRM_LEGACY |
371 | #ifdef __alpha__ |
372 | /* |
373 | * Default the hose |
374 | */ |
375 | if (!dev->hose) { |
376 | struct pci_dev *pci_dev; |
377 | |
378 | pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); |
379 | if (pci_dev) { |
380 | dev->hose = pci_dev->sysdata; |
381 | pci_dev_put(pci_dev); |
382 | } |
383 | if (!dev->hose) { |
384 | struct pci_bus *b = list_entry(pci_root_buses.next, |
385 | struct pci_bus, node); |
386 | if (b) |
387 | dev->hose = b->sysdata; |
388 | } |
389 | } |
390 | #endif |
391 | #endif |
392 | |
393 | return 0; |
394 | } |
395 | |
396 | /** |
397 | * drm_open - open method for DRM file |
398 | * @inode: device inode |
399 | * @filp: file pointer. |
400 | * |
401 | * This function must be used by drivers as their &file_operations.open method. |
402 | * It looks up the correct DRM device and instantiates all the per-file |
403 | * resources for it. It also calls the &drm_driver.open driver callback. |
404 | * |
405 | * RETURNS: |
406 | * |
407 | * 0 on success or negative errno value on failure. |
408 | */ |
409 | int drm_open(struct inode *inode, struct file *filp) |
410 | { |
411 | struct drm_device *dev; |
412 | struct drm_minor *minor; |
413 | int retcode; |
414 | int need_setup = 0; |
415 | |
416 | minor = drm_minor_acquire(minor_id: iminor(inode)); |
417 | if (IS_ERR(ptr: minor)) |
418 | return PTR_ERR(ptr: minor); |
419 | |
420 | dev = minor->dev; |
421 | if (drm_dev_needs_global_mutex(dev)) |
422 | mutex_lock(&drm_global_mutex); |
423 | |
424 | if (!atomic_fetch_inc(v: &dev->open_count)) |
425 | need_setup = 1; |
426 | |
427 | /* share address_space across all char-devs of a single device */ |
428 | filp->f_mapping = dev->anon_inode->i_mapping; |
429 | |
430 | retcode = drm_open_helper(filp, minor); |
431 | if (retcode) |
432 | goto err_undo; |
433 | if (need_setup) { |
434 | retcode = drm_legacy_setup(dev); |
435 | if (retcode) { |
436 | drm_close_helper(filp); |
437 | goto err_undo; |
438 | } |
439 | } |
440 | |
441 | if (drm_dev_needs_global_mutex(dev)) |
442 | mutex_unlock(lock: &drm_global_mutex); |
443 | |
444 | return 0; |
445 | |
446 | err_undo: |
447 | atomic_dec(v: &dev->open_count); |
448 | if (drm_dev_needs_global_mutex(dev)) |
449 | mutex_unlock(lock: &drm_global_mutex); |
450 | drm_minor_release(minor); |
451 | return retcode; |
452 | } |
453 | EXPORT_SYMBOL(drm_open); |
454 | |
455 | void drm_lastclose(struct drm_device * dev) |
456 | { |
457 | drm_dbg_core(dev, "\n" ); |
458 | |
459 | if (dev->driver->lastclose) |
460 | dev->driver->lastclose(dev); |
461 | drm_dbg_core(dev, "driver lastclose completed\n" ); |
462 | |
463 | if (drm_core_check_feature(dev, feature: DRIVER_LEGACY)) |
464 | drm_legacy_dev_reinit(dev); |
465 | |
466 | drm_client_dev_restore(dev); |
467 | } |
468 | |
469 | /** |
470 | * drm_release - release method for DRM file |
471 | * @inode: device inode |
472 | * @filp: file pointer. |
473 | * |
474 | * This function must be used by drivers as their &file_operations.release |
475 | * method. It frees any resources associated with the open file, and calls the |
476 | * &drm_driver.postclose driver callback. If this is the last open file for the |
477 | * DRM device also proceeds to call the &drm_driver.lastclose driver callback. |
478 | * |
479 | * RETURNS: |
480 | * |
481 | * Always succeeds and returns 0. |
482 | */ |
483 | int drm_release(struct inode *inode, struct file *filp) |
484 | { |
485 | struct drm_file *file_priv = filp->private_data; |
486 | struct drm_minor *minor = file_priv->minor; |
487 | struct drm_device *dev = minor->dev; |
488 | |
489 | if (drm_dev_needs_global_mutex(dev)) |
490 | mutex_lock(&drm_global_mutex); |
491 | |
492 | drm_dbg_core(dev, "open_count = %d\n" , atomic_read(&dev->open_count)); |
493 | |
494 | drm_close_helper(filp); |
495 | |
496 | if (atomic_dec_and_test(v: &dev->open_count)) |
497 | drm_lastclose(dev); |
498 | |
499 | if (drm_dev_needs_global_mutex(dev)) |
500 | mutex_unlock(lock: &drm_global_mutex); |
501 | |
502 | drm_minor_release(minor); |
503 | |
504 | return 0; |
505 | } |
506 | EXPORT_SYMBOL(drm_release); |
507 | |
508 | void drm_file_update_pid(struct drm_file *filp) |
509 | { |
510 | struct drm_device *dev; |
511 | struct pid *pid, *old; |
512 | |
513 | /* |
514 | * Master nodes need to keep the original ownership in order for |
515 | * drm_master_check_perm to keep working correctly. (See comment in |
516 | * drm_auth.c.) |
517 | */ |
518 | if (filp->was_master) |
519 | return; |
520 | |
521 | pid = task_tgid(current); |
522 | |
523 | /* |
524 | * Quick unlocked check since the model is a single handover followed by |
525 | * exclusive repeated use. |
526 | */ |
527 | if (pid == rcu_access_pointer(filp->pid)) |
528 | return; |
529 | |
530 | dev = filp->minor->dev; |
531 | mutex_lock(&dev->filelist_mutex); |
532 | old = rcu_replace_pointer(filp->pid, pid, 1); |
533 | mutex_unlock(lock: &dev->filelist_mutex); |
534 | |
535 | if (pid != old) { |
536 | get_pid(pid); |
537 | synchronize_rcu(); |
538 | put_pid(pid: old); |
539 | } |
540 | } |
541 | |
542 | /** |
543 | * drm_release_noglobal - release method for DRM file |
544 | * @inode: device inode |
545 | * @filp: file pointer. |
546 | * |
547 | * This function may be used by drivers as their &file_operations.release |
548 | * method. It frees any resources associated with the open file prior to taking |
549 | * the drm_global_mutex, which then calls the &drm_driver.postclose driver |
550 | * callback. If this is the last open file for the DRM device also proceeds to |
551 | * call the &drm_driver.lastclose driver callback. |
552 | * |
553 | * RETURNS: |
554 | * |
555 | * Always succeeds and returns 0. |
556 | */ |
557 | int drm_release_noglobal(struct inode *inode, struct file *filp) |
558 | { |
559 | struct drm_file *file_priv = filp->private_data; |
560 | struct drm_minor *minor = file_priv->minor; |
561 | struct drm_device *dev = minor->dev; |
562 | |
563 | drm_close_helper(filp); |
564 | |
565 | if (atomic_dec_and_mutex_lock(cnt: &dev->open_count, lock: &drm_global_mutex)) { |
566 | drm_lastclose(dev); |
567 | mutex_unlock(lock: &drm_global_mutex); |
568 | } |
569 | |
570 | drm_minor_release(minor); |
571 | |
572 | return 0; |
573 | } |
574 | EXPORT_SYMBOL(drm_release_noglobal); |
575 | |
576 | /** |
577 | * drm_read - read method for DRM file |
578 | * @filp: file pointer |
579 | * @buffer: userspace destination pointer for the read |
580 | * @count: count in bytes to read |
581 | * @offset: offset to read |
582 | * |
583 | * This function must be used by drivers as their &file_operations.read |
584 | * method if they use DRM events for asynchronous signalling to userspace. |
585 | * Since events are used by the KMS API for vblank and page flip completion this |
586 | * means all modern display drivers must use it. |
587 | * |
588 | * @offset is ignored, DRM events are read like a pipe. Polling support is |
589 | * provided by drm_poll(). |
590 | * |
591 | * This function will only ever read a full event. Therefore userspace must |
592 | * supply a big enough buffer to fit any event to ensure forward progress. Since |
593 | * the maximum event space is currently 4K it's recommended to just use that for |
594 | * safety. |
595 | * |
596 | * RETURNS: |
597 | * |
598 | * Number of bytes read (always aligned to full events, and can be 0) or a |
599 | * negative error code on failure. |
600 | */ |
601 | ssize_t drm_read(struct file *filp, char __user *buffer, |
602 | size_t count, loff_t *offset) |
603 | { |
604 | struct drm_file *file_priv = filp->private_data; |
605 | struct drm_device *dev = file_priv->minor->dev; |
606 | ssize_t ret; |
607 | |
608 | ret = mutex_lock_interruptible(&file_priv->event_read_lock); |
609 | if (ret) |
610 | return ret; |
611 | |
612 | for (;;) { |
613 | struct drm_pending_event *e = NULL; |
614 | |
615 | spin_lock_irq(lock: &dev->event_lock); |
616 | if (!list_empty(head: &file_priv->event_list)) { |
617 | e = list_first_entry(&file_priv->event_list, |
618 | struct drm_pending_event, link); |
619 | file_priv->event_space += e->event->length; |
620 | list_del(entry: &e->link); |
621 | } |
622 | spin_unlock_irq(lock: &dev->event_lock); |
623 | |
624 | if (e == NULL) { |
625 | if (ret) |
626 | break; |
627 | |
628 | if (filp->f_flags & O_NONBLOCK) { |
629 | ret = -EAGAIN; |
630 | break; |
631 | } |
632 | |
633 | mutex_unlock(lock: &file_priv->event_read_lock); |
634 | ret = wait_event_interruptible(file_priv->event_wait, |
635 | !list_empty(&file_priv->event_list)); |
636 | if (ret >= 0) |
637 | ret = mutex_lock_interruptible(&file_priv->event_read_lock); |
638 | if (ret) |
639 | return ret; |
640 | } else { |
641 | unsigned length = e->event->length; |
642 | |
643 | if (length > count - ret) { |
644 | put_back_event: |
645 | spin_lock_irq(lock: &dev->event_lock); |
646 | file_priv->event_space -= length; |
647 | list_add(new: &e->link, head: &file_priv->event_list); |
648 | spin_unlock_irq(lock: &dev->event_lock); |
649 | wake_up_interruptible_poll(&file_priv->event_wait, |
650 | EPOLLIN | EPOLLRDNORM); |
651 | break; |
652 | } |
653 | |
654 | if (copy_to_user(to: buffer + ret, from: e->event, n: length)) { |
655 | if (ret == 0) |
656 | ret = -EFAULT; |
657 | goto put_back_event; |
658 | } |
659 | |
660 | ret += length; |
661 | kfree(objp: e); |
662 | } |
663 | } |
664 | mutex_unlock(lock: &file_priv->event_read_lock); |
665 | |
666 | return ret; |
667 | } |
668 | EXPORT_SYMBOL(drm_read); |
669 | |
670 | /** |
671 | * drm_poll - poll method for DRM file |
672 | * @filp: file pointer |
673 | * @wait: poll waiter table |
674 | * |
675 | * This function must be used by drivers as their &file_operations.read method |
676 | * if they use DRM events for asynchronous signalling to userspace. Since |
677 | * events are used by the KMS API for vblank and page flip completion this means |
678 | * all modern display drivers must use it. |
679 | * |
680 | * See also drm_read(). |
681 | * |
682 | * RETURNS: |
683 | * |
684 | * Mask of POLL flags indicating the current status of the file. |
685 | */ |
686 | __poll_t drm_poll(struct file *filp, struct poll_table_struct *wait) |
687 | { |
688 | struct drm_file *file_priv = filp->private_data; |
689 | __poll_t mask = 0; |
690 | |
691 | poll_wait(filp, wait_address: &file_priv->event_wait, p: wait); |
692 | |
693 | if (!list_empty(head: &file_priv->event_list)) |
694 | mask |= EPOLLIN | EPOLLRDNORM; |
695 | |
696 | return mask; |
697 | } |
698 | EXPORT_SYMBOL(drm_poll); |
699 | |
700 | /** |
701 | * drm_event_reserve_init_locked - init a DRM event and reserve space for it |
702 | * @dev: DRM device |
703 | * @file_priv: DRM file private data |
704 | * @p: tracking structure for the pending event |
705 | * @e: actual event data to deliver to userspace |
706 | * |
707 | * This function prepares the passed in event for eventual delivery. If the event |
708 | * doesn't get delivered (because the IOCTL fails later on, before queuing up |
709 | * anything) then the even must be cancelled and freed using |
710 | * drm_event_cancel_free(). Successfully initialized events should be sent out |
711 | * using drm_send_event() or drm_send_event_locked() to signal completion of the |
712 | * asynchronous event to userspace. |
713 | * |
714 | * If callers embedded @p into a larger structure it must be allocated with |
715 | * kmalloc and @p must be the first member element. |
716 | * |
717 | * This is the locked version of drm_event_reserve_init() for callers which |
718 | * already hold &drm_device.event_lock. |
719 | * |
720 | * RETURNS: |
721 | * |
722 | * 0 on success or a negative error code on failure. |
723 | */ |
724 | int drm_event_reserve_init_locked(struct drm_device *dev, |
725 | struct drm_file *file_priv, |
726 | struct drm_pending_event *p, |
727 | struct drm_event *e) |
728 | { |
729 | if (file_priv->event_space < e->length) |
730 | return -ENOMEM; |
731 | |
732 | file_priv->event_space -= e->length; |
733 | |
734 | p->event = e; |
735 | list_add(new: &p->pending_link, head: &file_priv->pending_event_list); |
736 | p->file_priv = file_priv; |
737 | |
738 | return 0; |
739 | } |
740 | EXPORT_SYMBOL(drm_event_reserve_init_locked); |
741 | |
742 | /** |
743 | * drm_event_reserve_init - init a DRM event and reserve space for it |
744 | * @dev: DRM device |
745 | * @file_priv: DRM file private data |
746 | * @p: tracking structure for the pending event |
747 | * @e: actual event data to deliver to userspace |
748 | * |
749 | * This function prepares the passed in event for eventual delivery. If the event |
750 | * doesn't get delivered (because the IOCTL fails later on, before queuing up |
751 | * anything) then the even must be cancelled and freed using |
752 | * drm_event_cancel_free(). Successfully initialized events should be sent out |
753 | * using drm_send_event() or drm_send_event_locked() to signal completion of the |
754 | * asynchronous event to userspace. |
755 | * |
756 | * If callers embedded @p into a larger structure it must be allocated with |
757 | * kmalloc and @p must be the first member element. |
758 | * |
759 | * Callers which already hold &drm_device.event_lock should use |
760 | * drm_event_reserve_init_locked() instead. |
761 | * |
762 | * RETURNS: |
763 | * |
764 | * 0 on success or a negative error code on failure. |
765 | */ |
766 | int drm_event_reserve_init(struct drm_device *dev, |
767 | struct drm_file *file_priv, |
768 | struct drm_pending_event *p, |
769 | struct drm_event *e) |
770 | { |
771 | unsigned long flags; |
772 | int ret; |
773 | |
774 | spin_lock_irqsave(&dev->event_lock, flags); |
775 | ret = drm_event_reserve_init_locked(dev, file_priv, p, e); |
776 | spin_unlock_irqrestore(lock: &dev->event_lock, flags); |
777 | |
778 | return ret; |
779 | } |
780 | EXPORT_SYMBOL(drm_event_reserve_init); |
781 | |
782 | /** |
783 | * drm_event_cancel_free - free a DRM event and release its space |
784 | * @dev: DRM device |
785 | * @p: tracking structure for the pending event |
786 | * |
787 | * This function frees the event @p initialized with drm_event_reserve_init() |
788 | * and releases any allocated space. It is used to cancel an event when the |
789 | * nonblocking operation could not be submitted and needed to be aborted. |
790 | */ |
791 | void drm_event_cancel_free(struct drm_device *dev, |
792 | struct drm_pending_event *p) |
793 | { |
794 | unsigned long flags; |
795 | |
796 | spin_lock_irqsave(&dev->event_lock, flags); |
797 | if (p->file_priv) { |
798 | p->file_priv->event_space += p->event->length; |
799 | list_del(entry: &p->pending_link); |
800 | } |
801 | spin_unlock_irqrestore(lock: &dev->event_lock, flags); |
802 | |
803 | if (p->fence) |
804 | dma_fence_put(fence: p->fence); |
805 | |
806 | kfree(objp: p); |
807 | } |
808 | EXPORT_SYMBOL(drm_event_cancel_free); |
809 | |
810 | static void drm_send_event_helper(struct drm_device *dev, |
811 | struct drm_pending_event *e, ktime_t timestamp) |
812 | { |
813 | assert_spin_locked(&dev->event_lock); |
814 | |
815 | if (e->completion) { |
816 | complete_all(e->completion); |
817 | e->completion_release(e->completion); |
818 | e->completion = NULL; |
819 | } |
820 | |
821 | if (e->fence) { |
822 | if (timestamp) |
823 | dma_fence_signal_timestamp(fence: e->fence, timestamp); |
824 | else |
825 | dma_fence_signal(fence: e->fence); |
826 | dma_fence_put(fence: e->fence); |
827 | } |
828 | |
829 | if (!e->file_priv) { |
830 | kfree(objp: e); |
831 | return; |
832 | } |
833 | |
834 | list_del(entry: &e->pending_link); |
835 | list_add_tail(new: &e->link, |
836 | head: &e->file_priv->event_list); |
837 | wake_up_interruptible_poll(&e->file_priv->event_wait, |
838 | EPOLLIN | EPOLLRDNORM); |
839 | } |
840 | |
841 | /** |
842 | * drm_send_event_timestamp_locked - send DRM event to file descriptor |
843 | * @dev: DRM device |
844 | * @e: DRM event to deliver |
845 | * @timestamp: timestamp to set for the fence event in kernel's CLOCK_MONOTONIC |
846 | * time domain |
847 | * |
848 | * This function sends the event @e, initialized with drm_event_reserve_init(), |
849 | * to its associated userspace DRM file. Callers must already hold |
850 | * &drm_device.event_lock. |
851 | * |
852 | * Note that the core will take care of unlinking and disarming events when the |
853 | * corresponding DRM file is closed. Drivers need not worry about whether the |
854 | * DRM file for this event still exists and can call this function upon |
855 | * completion of the asynchronous work unconditionally. |
856 | */ |
857 | void drm_send_event_timestamp_locked(struct drm_device *dev, |
858 | struct drm_pending_event *e, ktime_t timestamp) |
859 | { |
860 | drm_send_event_helper(dev, e, timestamp); |
861 | } |
862 | EXPORT_SYMBOL(drm_send_event_timestamp_locked); |
863 | |
864 | /** |
865 | * drm_send_event_locked - send DRM event to file descriptor |
866 | * @dev: DRM device |
867 | * @e: DRM event to deliver |
868 | * |
869 | * This function sends the event @e, initialized with drm_event_reserve_init(), |
870 | * to its associated userspace DRM file. Callers must already hold |
871 | * &drm_device.event_lock, see drm_send_event() for the unlocked version. |
872 | * |
873 | * Note that the core will take care of unlinking and disarming events when the |
874 | * corresponding DRM file is closed. Drivers need not worry about whether the |
875 | * DRM file for this event still exists and can call this function upon |
876 | * completion of the asynchronous work unconditionally. |
877 | */ |
878 | void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) |
879 | { |
880 | drm_send_event_helper(dev, e, timestamp: 0); |
881 | } |
882 | EXPORT_SYMBOL(drm_send_event_locked); |
883 | |
884 | /** |
885 | * drm_send_event - send DRM event to file descriptor |
886 | * @dev: DRM device |
887 | * @e: DRM event to deliver |
888 | * |
889 | * This function sends the event @e, initialized with drm_event_reserve_init(), |
890 | * to its associated userspace DRM file. This function acquires |
891 | * &drm_device.event_lock, see drm_send_event_locked() for callers which already |
892 | * hold this lock. |
893 | * |
894 | * Note that the core will take care of unlinking and disarming events when the |
895 | * corresponding DRM file is closed. Drivers need not worry about whether the |
896 | * DRM file for this event still exists and can call this function upon |
897 | * completion of the asynchronous work unconditionally. |
898 | */ |
899 | void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) |
900 | { |
901 | unsigned long irqflags; |
902 | |
903 | spin_lock_irqsave(&dev->event_lock, irqflags); |
904 | drm_send_event_helper(dev, e, timestamp: 0); |
905 | spin_unlock_irqrestore(lock: &dev->event_lock, flags: irqflags); |
906 | } |
907 | EXPORT_SYMBOL(drm_send_event); |
908 | |
909 | static void print_size(struct drm_printer *p, const char *stat, |
910 | const char *region, u64 sz) |
911 | { |
912 | const char *units[] = {"" , " KiB" , " MiB" }; |
913 | unsigned u; |
914 | |
915 | for (u = 0; u < ARRAY_SIZE(units) - 1; u++) { |
916 | if (sz < SZ_1K) |
917 | break; |
918 | sz = div_u64(dividend: sz, SZ_1K); |
919 | } |
920 | |
921 | drm_printf(p, f: "drm-%s-%s:\t%llu%s\n" , stat, region, sz, units[u]); |
922 | } |
923 | |
924 | /** |
925 | * drm_print_memory_stats - A helper to print memory stats |
926 | * @p: The printer to print output to |
927 | * @stats: The collected memory stats |
928 | * @supported_status: Bitmask of optional stats which are available |
929 | * @region: The memory region |
930 | * |
931 | */ |
932 | void drm_print_memory_stats(struct drm_printer *p, |
933 | const struct drm_memory_stats *stats, |
934 | enum drm_gem_object_status supported_status, |
935 | const char *region) |
936 | { |
937 | print_size(p, stat: "total" , region, sz: stats->private + stats->shared); |
938 | print_size(p, stat: "shared" , region, sz: stats->shared); |
939 | print_size(p, stat: "active" , region, sz: stats->active); |
940 | |
941 | if (supported_status & DRM_GEM_OBJECT_RESIDENT) |
942 | print_size(p, stat: "resident" , region, sz: stats->resident); |
943 | |
944 | if (supported_status & DRM_GEM_OBJECT_PURGEABLE) |
945 | print_size(p, stat: "purgeable" , region, sz: stats->purgeable); |
946 | } |
947 | EXPORT_SYMBOL(drm_print_memory_stats); |
948 | |
949 | /** |
950 | * drm_show_memory_stats - Helper to collect and show standard fdinfo memory stats |
951 | * @p: the printer to print output to |
952 | * @file: the DRM file |
953 | * |
954 | * Helper to iterate over GEM objects with a handle allocated in the specified |
955 | * file. |
956 | */ |
957 | void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file) |
958 | { |
959 | struct drm_gem_object *obj; |
960 | struct drm_memory_stats status = {}; |
961 | enum drm_gem_object_status supported_status; |
962 | int id; |
963 | |
964 | spin_lock(lock: &file->table_lock); |
965 | idr_for_each_entry (&file->object_idr, obj, id) { |
966 | enum drm_gem_object_status s = 0; |
967 | size_t add_size = (obj->funcs && obj->funcs->rss) ? |
968 | obj->funcs->rss(obj) : obj->size; |
969 | |
970 | if (obj->funcs && obj->funcs->status) { |
971 | s = obj->funcs->status(obj); |
972 | supported_status = DRM_GEM_OBJECT_RESIDENT | |
973 | DRM_GEM_OBJECT_PURGEABLE; |
974 | } |
975 | |
976 | if (obj->handle_count > 1) { |
977 | status.shared += obj->size; |
978 | } else { |
979 | status.private += obj->size; |
980 | } |
981 | |
982 | if (s & DRM_GEM_OBJECT_RESIDENT) { |
983 | status.resident += add_size; |
984 | } else { |
985 | /* If already purged or not yet backed by pages, don't |
986 | * count it as purgeable: |
987 | */ |
988 | s &= ~DRM_GEM_OBJECT_PURGEABLE; |
989 | } |
990 | |
991 | if (!dma_resv_test_signaled(obj: obj->resv, usage: dma_resv_usage_rw(write: true))) { |
992 | status.active += add_size; |
993 | |
994 | /* If still active, don't count as purgeable: */ |
995 | s &= ~DRM_GEM_OBJECT_PURGEABLE; |
996 | } |
997 | |
998 | if (s & DRM_GEM_OBJECT_PURGEABLE) |
999 | status.purgeable += add_size; |
1000 | } |
1001 | spin_unlock(lock: &file->table_lock); |
1002 | |
1003 | drm_print_memory_stats(p, &status, supported_status, "memory" ); |
1004 | } |
1005 | EXPORT_SYMBOL(drm_show_memory_stats); |
1006 | |
1007 | /** |
1008 | * drm_show_fdinfo - helper for drm file fops |
1009 | * @m: output stream |
1010 | * @f: the device file instance |
1011 | * |
1012 | * Helper to implement fdinfo, for userspace to query usage stats, etc, of a |
1013 | * process using the GPU. See also &drm_driver.show_fdinfo. |
1014 | * |
1015 | * For text output format description please see Documentation/gpu/drm-usage-stats.rst |
1016 | */ |
1017 | void drm_show_fdinfo(struct seq_file *m, struct file *f) |
1018 | { |
1019 | struct drm_file *file = f->private_data; |
1020 | struct drm_device *dev = file->minor->dev; |
1021 | struct drm_printer p = drm_seq_file_printer(f: m); |
1022 | |
1023 | drm_printf(p: &p, f: "drm-driver:\t%s\n" , dev->driver->name); |
1024 | drm_printf(p: &p, f: "drm-client-id:\t%llu\n" , file->client_id); |
1025 | |
1026 | if (dev_is_pci(dev->dev)) { |
1027 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
1028 | |
1029 | drm_printf(p: &p, f: "drm-pdev:\t%04x:%02x:%02x.%d\n" , |
1030 | pci_domain_nr(bus: pdev->bus), pdev->bus->number, |
1031 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); |
1032 | } |
1033 | |
1034 | if (dev->driver->show_fdinfo) |
1035 | dev->driver->show_fdinfo(&p, file); |
1036 | } |
1037 | EXPORT_SYMBOL(drm_show_fdinfo); |
1038 | |
1039 | /** |
1040 | * mock_drm_getfile - Create a new struct file for the drm device |
1041 | * @minor: drm minor to wrap (e.g. #drm_device.primary) |
1042 | * @flags: file creation mode (O_RDWR etc) |
1043 | * |
1044 | * This create a new struct file that wraps a DRM file context around a |
1045 | * DRM minor. This mimicks userspace opening e.g. /dev/dri/card0, but without |
1046 | * invoking userspace. The struct file may be operated on using its f_op |
1047 | * (the drm_device.driver.fops) to mimick userspace operations, or be supplied |
1048 | * to userspace facing functions as an internal/anonymous client. |
1049 | * |
1050 | * RETURNS: |
1051 | * Pointer to newly created struct file, ERR_PTR on failure. |
1052 | */ |
1053 | struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags) |
1054 | { |
1055 | struct drm_device *dev = minor->dev; |
1056 | struct drm_file *priv; |
1057 | struct file *file; |
1058 | |
1059 | priv = drm_file_alloc(minor); |
1060 | if (IS_ERR(ptr: priv)) |
1061 | return ERR_CAST(ptr: priv); |
1062 | |
1063 | file = anon_inode_getfile(name: "drm" , fops: dev->driver->fops, priv, flags); |
1064 | if (IS_ERR(ptr: file)) { |
1065 | drm_file_free(file: priv); |
1066 | return file; |
1067 | } |
1068 | |
1069 | /* Everyone shares a single global address space */ |
1070 | file->f_mapping = dev->anon_inode->i_mapping; |
1071 | |
1072 | drm_dev_get(dev); |
1073 | priv->filp = file; |
1074 | |
1075 | return file; |
1076 | } |
1077 | EXPORT_SYMBOL_FOR_TESTS_ONLY(mock_drm_getfile); |
1078 | |