1a85cb24fSFrançois Tigeot /* 2a85cb24fSFrançois Tigeot * \author Rickard E. (Rik) Faith <faith@valinux.com> 3a85cb24fSFrançois Tigeot * \author Daryll Strauss <daryll@valinux.com> 4a85cb24fSFrançois Tigeot * \author Gareth Hughes <gareth@valinux.com> 5a85cb24fSFrançois Tigeot */ 6a85cb24fSFrançois Tigeot 7a85cb24fSFrançois Tigeot /* 8a85cb24fSFrançois Tigeot * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com 9a85cb24fSFrançois Tigeot * 10a85cb24fSFrançois Tigeot * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11a85cb24fSFrançois Tigeot * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12a85cb24fSFrançois Tigeot * All Rights Reserved. 13a85cb24fSFrançois Tigeot * 14a85cb24fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 15a85cb24fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 16a85cb24fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 17a85cb24fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18a85cb24fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 19a85cb24fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 20a85cb24fSFrançois Tigeot * 21a85cb24fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 22a85cb24fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 23a85cb24fSFrançois Tigeot * Software. 24a85cb24fSFrançois Tigeot * 25a85cb24fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26a85cb24fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27a85cb24fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28a85cb24fSFrançois Tigeot * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29a85cb24fSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30a85cb24fSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 31a85cb24fSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE. 32a85cb24fSFrançois Tigeot */ 33a85cb24fSFrançois Tigeot 34a85cb24fSFrançois Tigeot #include <sys/types.h> 35a85cb24fSFrançois Tigeot #include <sys/uio.h> /* must come first to avoid kfree() macros issues */ 36a85cb24fSFrançois Tigeot 37a85cb24fSFrançois Tigeot #include <linux/poll.h> 38a85cb24fSFrançois Tigeot #include <linux/slab.h> 39a85cb24fSFrançois Tigeot #include <linux/module.h> 40a85cb24fSFrançois Tigeot 41a85cb24fSFrançois Tigeot #include <drm/drm_file.h> 42a85cb24fSFrançois Tigeot #include <drm/drmP.h> 43a85cb24fSFrançois Tigeot 44a85cb24fSFrançois Tigeot #include "drm_legacy.h" 45a85cb24fSFrançois Tigeot #include "drm_internal.h" 46a85cb24fSFrançois Tigeot #include "drm_crtc_internal.h" 47a85cb24fSFrançois Tigeot 48a85cb24fSFrançois Tigeot /* from BKL pushdown */ 49a85cb24fSFrançois Tigeot DEFINE_MUTEX(drm_global_mutex); 50a85cb24fSFrançois Tigeot 51a85cb24fSFrançois Tigeot /** 52a85cb24fSFrançois Tigeot * DOC: file operations 53a85cb24fSFrançois Tigeot * 54a85cb24fSFrançois Tigeot * Drivers must define the file operations structure that forms the DRM 55a85cb24fSFrançois Tigeot * userspace API entry point, even though most of those operations are 563f2dd94aSFrançois Tigeot * implemented in the DRM core. The resulting &struct file_operations must be 573f2dd94aSFrançois Tigeot * stored in the &drm_driver.fops field. The mandatory functions are drm_open(), 58a85cb24fSFrançois Tigeot * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled 593f2dd94aSFrançois Tigeot * Note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n, so there's no 603f2dd94aSFrançois Tigeot * need to sprinkle #ifdef into the code. Drivers which implement private ioctls 613f2dd94aSFrançois Tigeot * that require 32/64 bit compatibility support must provide their own 623f2dd94aSFrançois Tigeot * &file_operations.compat_ioctl handler that processes private ioctls and calls 633f2dd94aSFrançois Tigeot * drm_compat_ioctl() for core ioctls. 64a85cb24fSFrançois Tigeot * 65a85cb24fSFrançois Tigeot * In addition drm_read() and drm_poll() provide support for DRM events. DRM 66a85cb24fSFrançois Tigeot * events are a generic and extensible means to send asynchronous events to 67a85cb24fSFrançois Tigeot * userspace through the file descriptor. They are used to send vblank event and 68a85cb24fSFrançois Tigeot * page flip completions by the KMS API. But drivers can also use it for their 69a85cb24fSFrançois Tigeot * own needs, e.g. to signal completion of rendering. 70a85cb24fSFrançois Tigeot * 713f2dd94aSFrançois Tigeot * For the driver-side event interface see drm_event_reserve_init() and 723f2dd94aSFrançois Tigeot * drm_send_event() as the main starting points. 733f2dd94aSFrançois Tigeot * 74a85cb24fSFrançois Tigeot * The memory mapping implementation will vary depending on how the driver 75a85cb24fSFrançois Tigeot * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap() 76a85cb24fSFrançois Tigeot * function, modern drivers should use one of the provided memory-manager 773f2dd94aSFrançois Tigeot * specific implementations. For GEM-based drivers this is drm_gem_mmap(), and 783f2dd94aSFrançois Tigeot * for drivers which use the CMA GEM helpers it's drm_gem_cma_mmap(). 79a85cb24fSFrançois Tigeot * 80a85cb24fSFrançois Tigeot * No other file operations are supported by the DRM userspace API. Overall the 813f2dd94aSFrançois Tigeot * following is an example &file_operations structure:: 82a85cb24fSFrançois Tigeot * 83a85cb24fSFrançois Tigeot * static const example_drm_fops = { 84a85cb24fSFrançois Tigeot * .owner = THIS_MODULE, 85a85cb24fSFrançois Tigeot * .open = drm_open, 86a85cb24fSFrançois Tigeot * .release = drm_release, 87a85cb24fSFrançois Tigeot * .unlocked_ioctl = drm_ioctl, 88a85cb24fSFrançois Tigeot * .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n 89a85cb24fSFrançois Tigeot * .poll = drm_poll, 90a85cb24fSFrançois Tigeot * .read = drm_read, 91a85cb24fSFrançois Tigeot * .llseek = no_llseek, 92a85cb24fSFrançois Tigeot * .mmap = drm_gem_mmap, 93a85cb24fSFrançois Tigeot * }; 943f2dd94aSFrançois Tigeot * 953f2dd94aSFrançois Tigeot * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for 963f2dd94aSFrançois Tigeot * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this 973f2dd94aSFrançois Tigeot * simpler. 983f2dd94aSFrançois Tigeot * 993f2dd94aSFrançois Tigeot * The driver's &file_operations must be stored in &drm_driver.fops. 1003f2dd94aSFrançois Tigeot * 1013f2dd94aSFrançois Tigeot * For driver-private IOCTL handling see the more detailed discussion in 1023f2dd94aSFrançois Tigeot * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`. 103a85cb24fSFrançois Tigeot */ 104a85cb24fSFrançois Tigeot 1053f2dd94aSFrançois Tigeot static int drm_open_helper(struct cdev *kdev, int flags, 1063f2dd94aSFrançois Tigeot struct file *filp, struct drm_minor *minor); 107a85cb24fSFrançois Tigeot 108a85cb24fSFrançois Tigeot static int drm_setup(struct drm_device * dev) 109a85cb24fSFrançois Tigeot { 110a85cb24fSFrançois Tigeot int ret; 111a85cb24fSFrançois Tigeot 112a85cb24fSFrançois Tigeot if (dev->driver->firstopen && 113a85cb24fSFrançois Tigeot drm_core_check_feature(dev, DRIVER_LEGACY)) { 114a85cb24fSFrançois Tigeot ret = dev->driver->firstopen(dev); 115a85cb24fSFrançois Tigeot if (ret != 0) 116a85cb24fSFrançois Tigeot return ret; 117a85cb24fSFrançois Tigeot } 118a85cb24fSFrançois Tigeot 119a85cb24fSFrançois Tigeot ret = drm_legacy_dma_setup(dev); 120a85cb24fSFrançois Tigeot if (ret < 0) 121a85cb24fSFrançois Tigeot return ret; 122a85cb24fSFrançois Tigeot 123a85cb24fSFrançois Tigeot 124a85cb24fSFrançois Tigeot DRM_DEBUG("\n"); 125a85cb24fSFrançois Tigeot return 0; 126a85cb24fSFrançois Tigeot } 127a85cb24fSFrançois Tigeot 128a85cb24fSFrançois Tigeot /** 129a85cb24fSFrançois Tigeot * drm_open - open method for DRM file 130a85cb24fSFrançois Tigeot * @inode: device inode 131a85cb24fSFrançois Tigeot * @filp: file pointer. 132a85cb24fSFrançois Tigeot * 1333f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.open method. 1343f2dd94aSFrançois Tigeot * It looks up the correct DRM device and instantiates all the per-file 1353f2dd94aSFrançois Tigeot * resources for it. It also calls the &drm_driver.open driver callback. 136a85cb24fSFrançois Tigeot * 137a85cb24fSFrançois Tigeot * RETURNS: 138a85cb24fSFrançois Tigeot * 139a85cb24fSFrançois Tigeot * 0 on success or negative errno value on falure. 140a85cb24fSFrançois Tigeot */ 141a85cb24fSFrançois Tigeot // drm_open() is a file_operations function, not a dev_ops function 142a85cb24fSFrançois Tigeot // int drm_open(struct inode *inode, struct file *filp) 143a85cb24fSFrançois Tigeot int drm_open(struct dev_open_args *ap) 144a85cb24fSFrançois Tigeot { 1453f2dd94aSFrançois Tigeot #ifdef __DragonFly__ 146*5bd45597SMatthew Dillon struct file *filp = ap->a_fpp ? *ap->a_fpp : NULL; 147a85cb24fSFrançois Tigeot struct inode *inode = filp->f_data; /* A Linux inode is a Unix vnode */ 148a85cb24fSFrançois Tigeot struct cdev *kdev = ap->a_head.a_dev; 149a85cb24fSFrançois Tigeot int flags = ap->a_oflags; 1503f2dd94aSFrançois Tigeot #endif 1513f2dd94aSFrançois Tigeot struct drm_device *dev; 1523f2dd94aSFrançois Tigeot struct drm_minor *minor; 153a85cb24fSFrançois Tigeot int retcode; 154a85cb24fSFrançois Tigeot int need_setup = 0; 155a85cb24fSFrançois Tigeot 156a85cb24fSFrançois Tigeot minor = drm_minor_acquire(iminor(inode)); 1573f2dd94aSFrançois Tigeot if (IS_ERR(minor)) 1583f2dd94aSFrançois Tigeot return PTR_ERR(minor); 1593f2dd94aSFrançois Tigeot 1603f2dd94aSFrançois Tigeot dev = minor->dev; 161a85cb24fSFrançois Tigeot if (!dev->open_count++) 162a85cb24fSFrançois Tigeot need_setup = 1; 163a85cb24fSFrançois Tigeot 164a85cb24fSFrançois Tigeot /* share address_space across all char-devs of a single device */ 165a85cb24fSFrançois Tigeot #if 0 166a85cb24fSFrançois Tigeot filp->f_mapping = dev->anon_inode->i_mapping; 167a85cb24fSFrançois Tigeot #endif 168a85cb24fSFrançois Tigeot 169*5bd45597SMatthew Dillon #ifdef __DragonFly__ 170*5bd45597SMatthew Dillon retcode = drm_open_helper(kdev, flags, filp, minor); 171*5bd45597SMatthew Dillon #else 1723f2dd94aSFrançois Tigeot retcode = drm_open_helper(kdev, flags, ap->a_fp, minor); 173*5bd45597SMatthew Dillon #endif 1743f2dd94aSFrançois Tigeot if (retcode) 1753f2dd94aSFrançois Tigeot goto err_undo; 176a85cb24fSFrançois Tigeot if (need_setup) { 177a85cb24fSFrançois Tigeot retcode = drm_setup(dev); 178a85cb24fSFrançois Tigeot if (retcode) 179a85cb24fSFrançois Tigeot goto err_undo; 180a85cb24fSFrançois Tigeot } 1813f2dd94aSFrançois Tigeot #ifdef __DragonFly__ 1823f2dd94aSFrançois Tigeot device_busy(dev->dev->bsddev); 1833f2dd94aSFrançois Tigeot #endif 184a85cb24fSFrançois Tigeot return 0; 185a85cb24fSFrançois Tigeot 186a85cb24fSFrançois Tigeot err_undo: 187a85cb24fSFrançois Tigeot dev->open_count--; 188a85cb24fSFrançois Tigeot drm_minor_release(minor); 189a85cb24fSFrançois Tigeot return retcode; 190a85cb24fSFrançois Tigeot } 191a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_open); 192a85cb24fSFrançois Tigeot 193a85cb24fSFrançois Tigeot /* 194a85cb24fSFrançois Tigeot * Check whether DRI will run on this CPU. 195a85cb24fSFrançois Tigeot * 196a85cb24fSFrançois Tigeot * \return non-zero if the DRI will run on this CPU, or zero otherwise. 197a85cb24fSFrançois Tigeot */ 1983f2dd94aSFrançois Tigeot static int drm_cpu_valid(void) 1993f2dd94aSFrançois Tigeot { 2003f2dd94aSFrançois Tigeot #if defined(__sparc__) && !defined(__sparc_v9__) 2013f2dd94aSFrançois Tigeot return 0; /* No cmpxchg before v9 sparc. */ 2023f2dd94aSFrançois Tigeot #endif 2033f2dd94aSFrançois Tigeot return 1; 2043f2dd94aSFrançois Tigeot } 205a85cb24fSFrançois Tigeot 206a85cb24fSFrançois Tigeot /* 207a85cb24fSFrançois Tigeot * Called whenever a process opens /dev/drm. 208a85cb24fSFrançois Tigeot * 209a85cb24fSFrançois Tigeot * \param filp file pointer. 210a85cb24fSFrançois Tigeot * \param minor acquired minor-object. 211a85cb24fSFrançois Tigeot * \return zero on success or a negative number on failure. 212a85cb24fSFrançois Tigeot * 213a85cb24fSFrançois Tigeot * Creates and initializes a drm_file structure for the file private data in \p 214a85cb24fSFrançois Tigeot * filp and add it into the double linked list in \p dev. 215a85cb24fSFrançois Tigeot */ 2163f2dd94aSFrançois Tigeot static int drm_open_helper(struct cdev *kdev, int flags, 2173f2dd94aSFrançois Tigeot struct file *filp, struct drm_minor *minor) 218a85cb24fSFrançois Tigeot { 2193f2dd94aSFrançois Tigeot struct drm_device *dev = minor->dev; 220a85cb24fSFrançois Tigeot struct drm_file *priv; 221a85cb24fSFrançois Tigeot int ret; 222a85cb24fSFrançois Tigeot 223a85cb24fSFrançois Tigeot if (flags & O_EXCL) 2243f2dd94aSFrançois Tigeot return -EBUSY; /* No exclusive opens */ 2253f2dd94aSFrançois Tigeot if (!drm_cpu_valid()) 2263f2dd94aSFrançois Tigeot return -EINVAL; 227a85cb24fSFrançois Tigeot 2283f2dd94aSFrançois Tigeot DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, minor->index); 229a85cb24fSFrançois Tigeot 230a85cb24fSFrançois Tigeot priv = kzalloc(sizeof(*priv), GFP_KERNEL); 231a85cb24fSFrançois Tigeot if (!priv) 232a85cb24fSFrançois Tigeot return -ENOMEM; 233a85cb24fSFrançois Tigeot 234a85cb24fSFrançois Tigeot filp->private_data = priv; 235a85cb24fSFrançois Tigeot priv->filp = filp; 2363f2dd94aSFrançois Tigeot priv->pid = curproc->p_pid; 237a85cb24fSFrançois Tigeot priv->minor = minor; 238a85cb24fSFrançois Tigeot priv->dev = dev; 239a85cb24fSFrançois Tigeot 240a85cb24fSFrançois Tigeot /* for compatibility root is always authenticated */ 241a85cb24fSFrançois Tigeot priv->authenticated = capable(CAP_SYS_ADMIN); 242a85cb24fSFrançois Tigeot priv->lock_count = 0; 243a85cb24fSFrançois Tigeot 244a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->lhead); 245a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->fbs); 246a85cb24fSFrançois Tigeot lockinit(&priv->fbs_lock, "dpfl", 0, LK_CANRECURSE); 247a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->blobs); 248a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->pending_event_list); 249a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->event_list); 250a85cb24fSFrançois Tigeot init_waitqueue_head(&priv->event_wait); 251a85cb24fSFrançois Tigeot priv->event_space = 4096; /* set aside 4k for event buffer */ 252a85cb24fSFrançois Tigeot 253a85cb24fSFrançois Tigeot lockinit(&priv->event_read_lock, "dperl", 0, LK_CANRECURSE); 254a85cb24fSFrançois Tigeot 255a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 256a85cb24fSFrançois Tigeot drm_gem_open(dev, priv); 257a85cb24fSFrançois Tigeot 2583f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 2593f2dd94aSFrançois Tigeot drm_syncobj_open(priv); 2603f2dd94aSFrançois Tigeot 2613f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 2623f2dd94aSFrançois Tigeot drm_prime_init_file_private(&priv->prime); 2633f2dd94aSFrançois Tigeot 264a85cb24fSFrançois Tigeot if (dev->driver->open) { 265a85cb24fSFrançois Tigeot /* shared code returns -errno */ 266a85cb24fSFrançois Tigeot ret = -dev->driver->open(dev, priv); 2673f2dd94aSFrançois Tigeot if (ret != 0) 2683f2dd94aSFrançois Tigeot goto out_prime_destroy; 269a85cb24fSFrançois Tigeot } 270a85cb24fSFrançois Tigeot 271a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 2723f2dd94aSFrançois Tigeot kdev->si_drv1 = dev; 273a85cb24fSFrançois Tigeot #endif 274a85cb24fSFrançois Tigeot 2753f2dd94aSFrançois Tigeot if (drm_is_primary_client(priv)) { 2763f2dd94aSFrançois Tigeot ret = drm_master_open(priv); 2773f2dd94aSFrançois Tigeot if (ret) 2783f2dd94aSFrançois Tigeot goto out_close; 2793f2dd94aSFrançois Tigeot } 2803f2dd94aSFrançois Tigeot 281a85cb24fSFrançois Tigeot mutex_lock(&dev->filelist_mutex); 282a85cb24fSFrançois Tigeot list_add(&priv->lhead, &dev->filelist); 283a85cb24fSFrançois Tigeot mutex_unlock(&dev->filelist_mutex); 284a85cb24fSFrançois Tigeot 2853f2dd94aSFrançois Tigeot #ifdef __alpha__ 2863f2dd94aSFrançois Tigeot /* 2873f2dd94aSFrançois Tigeot * Default the hose 2883f2dd94aSFrançois Tigeot */ 2893f2dd94aSFrançois Tigeot if (!dev->hose) { 2903f2dd94aSFrançois Tigeot struct pci_dev *pci_dev; 2913f2dd94aSFrançois Tigeot pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); 2923f2dd94aSFrançois Tigeot if (pci_dev) { 2933f2dd94aSFrançois Tigeot dev->hose = pci_dev->sysdata; 2943f2dd94aSFrançois Tigeot pci_dev_put(pci_dev); 2953f2dd94aSFrançois Tigeot } 2963f2dd94aSFrançois Tigeot if (!dev->hose) { 2973f2dd94aSFrançois Tigeot struct pci_bus *b = list_entry(pci_root_buses.next, 2983f2dd94aSFrançois Tigeot struct pci_bus, node); 2993f2dd94aSFrançois Tigeot if (b) 3003f2dd94aSFrançois Tigeot dev->hose = b->sysdata; 3013f2dd94aSFrançois Tigeot } 3023f2dd94aSFrançois Tigeot } 303a85cb24fSFrançois Tigeot #endif 3043f2dd94aSFrançois Tigeot 3053f2dd94aSFrançois Tigeot return 0; 3063f2dd94aSFrançois Tigeot 3073f2dd94aSFrançois Tigeot out_close: 308a85cb24fSFrançois Tigeot if (dev->driver->postclose) 309a85cb24fSFrançois Tigeot dev->driver->postclose(dev, priv); 3103f2dd94aSFrançois Tigeot out_prime_destroy: 3113f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 3123f2dd94aSFrançois Tigeot drm_prime_destroy_file_private(&priv->prime); 3133f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 3143f2dd94aSFrançois Tigeot drm_syncobj_release(priv); 315a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 316a85cb24fSFrançois Tigeot drm_gem_release(dev, priv); 317a85cb24fSFrançois Tigeot put_pid(priv->pid); 318a85cb24fSFrançois Tigeot kfree(priv); 319a85cb24fSFrançois Tigeot filp->private_data = NULL; 320a85cb24fSFrançois Tigeot return ret; 321a85cb24fSFrançois Tigeot } 322a85cb24fSFrançois Tigeot 323a85cb24fSFrançois Tigeot static void drm_events_release(struct drm_file *file_priv) 324a85cb24fSFrançois Tigeot { 325a85cb24fSFrançois Tigeot struct drm_device *dev = file_priv->minor->dev; 326a85cb24fSFrançois Tigeot struct drm_pending_event *e, *et; 327a85cb24fSFrançois Tigeot unsigned long flags; 328a85cb24fSFrançois Tigeot 329a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 330a85cb24fSFrançois Tigeot 331a85cb24fSFrançois Tigeot /* Unlink pending events */ 332a85cb24fSFrançois Tigeot list_for_each_entry_safe(e, et, &file_priv->pending_event_list, 333a85cb24fSFrançois Tigeot pending_link) { 334a85cb24fSFrançois Tigeot list_del(&e->pending_link); 335a85cb24fSFrançois Tigeot e->file_priv = NULL; 336a85cb24fSFrançois Tigeot } 337a85cb24fSFrançois Tigeot 338a85cb24fSFrançois Tigeot /* Remove unconsumed events */ 339a85cb24fSFrançois Tigeot list_for_each_entry_safe(e, et, &file_priv->event_list, link) { 340a85cb24fSFrançois Tigeot list_del(&e->link); 341a85cb24fSFrançois Tigeot kfree(e); 342a85cb24fSFrançois Tigeot } 343a85cb24fSFrançois Tigeot 344a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 345a85cb24fSFrançois Tigeot } 346a85cb24fSFrançois Tigeot 347a85cb24fSFrançois Tigeot static void drm_legacy_dev_reinit(struct drm_device *dev) 348a85cb24fSFrançois Tigeot { 349a85cb24fSFrançois Tigeot if (dev->irq_enabled) 350a85cb24fSFrançois Tigeot drm_irq_uninstall(dev); 351a85cb24fSFrançois Tigeot 352a85cb24fSFrançois Tigeot mutex_lock(&dev->struct_mutex); 353a85cb24fSFrançois Tigeot 354a85cb24fSFrançois Tigeot drm_legacy_agp_clear(dev); 355a85cb24fSFrançois Tigeot 356a85cb24fSFrançois Tigeot drm_legacy_sg_cleanup(dev); 357a85cb24fSFrançois Tigeot drm_legacy_vma_flush(dev); 358a85cb24fSFrançois Tigeot drm_legacy_dma_takedown(dev); 359a85cb24fSFrançois Tigeot 360a85cb24fSFrançois Tigeot mutex_unlock(&dev->struct_mutex); 361a85cb24fSFrançois Tigeot 362a85cb24fSFrançois Tigeot dev->sigdata.lock = NULL; 363a85cb24fSFrançois Tigeot 364a85cb24fSFrançois Tigeot dev->context_flag = 0; 365a85cb24fSFrançois Tigeot dev->last_context = 0; 366a85cb24fSFrançois Tigeot dev->if_version = 0; 367a85cb24fSFrançois Tigeot 368a85cb24fSFrançois Tigeot DRM_DEBUG("lastclose completed\n"); 369a85cb24fSFrançois Tigeot } 370a85cb24fSFrançois Tigeot 371a85cb24fSFrançois Tigeot void drm_lastclose(struct drm_device * dev) 372a85cb24fSFrançois Tigeot { 373a85cb24fSFrançois Tigeot DRM_DEBUG("\n"); 374a85cb24fSFrançois Tigeot 375a85cb24fSFrançois Tigeot if (dev->driver->lastclose) 376a85cb24fSFrançois Tigeot dev->driver->lastclose(dev); 377a85cb24fSFrançois Tigeot DRM_DEBUG("driver lastclose completed\n"); 378a85cb24fSFrançois Tigeot 379a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY)) 380a85cb24fSFrançois Tigeot drm_legacy_dev_reinit(dev); 381a85cb24fSFrançois Tigeot } 382a85cb24fSFrançois Tigeot 383a85cb24fSFrançois Tigeot /** 384a85cb24fSFrançois Tigeot * drm_release - release method for DRM file 385a85cb24fSFrançois Tigeot * @inode: device inode 386a85cb24fSFrançois Tigeot * @filp: file pointer. 387a85cb24fSFrançois Tigeot * 3883f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.release 3893f2dd94aSFrançois Tigeot * method. It frees any resources associated with the open file, and calls the 3903f2dd94aSFrançois Tigeot * &drm_driver.postclose driver callback. If this is the last open file for the 3913f2dd94aSFrançois Tigeot * DRM device also proceeds to call the &drm_driver.lastclose driver callback. 392a85cb24fSFrançois Tigeot * 393a85cb24fSFrançois Tigeot * RETURNS: 394a85cb24fSFrançois Tigeot * 395a85cb24fSFrançois Tigeot * Always succeeds and returns 0. 396a85cb24fSFrançois Tigeot */ 397a85cb24fSFrançois Tigeot int drm_release(struct inode *inode, struct file *filp) 398a85cb24fSFrançois Tigeot { 399a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 400a85cb24fSFrançois Tigeot struct drm_minor *minor = file_priv->minor; 401a85cb24fSFrançois Tigeot struct drm_device *dev = minor->dev; 402a85cb24fSFrançois Tigeot 403a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 404a85cb24fSFrançois Tigeot /* dev is not correctly set yet */ 405a85cb24fSFrançois Tigeot return 0; 406a85cb24fSFrançois Tigeot #endif 407a85cb24fSFrançois Tigeot 408a85cb24fSFrançois Tigeot mutex_lock(&drm_global_mutex); 409a85cb24fSFrançois Tigeot 410a85cb24fSFrançois Tigeot DRM_DEBUG("open_count = %d\n", dev->open_count); 411a85cb24fSFrançois Tigeot 412a85cb24fSFrançois Tigeot mutex_lock(&dev->filelist_mutex); 413a85cb24fSFrançois Tigeot list_del(&file_priv->lhead); 414a85cb24fSFrançois Tigeot mutex_unlock(&dev->filelist_mutex); 415a85cb24fSFrançois Tigeot 4163f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY) && 4173f2dd94aSFrançois Tigeot dev->driver->preclose) 418a85cb24fSFrançois Tigeot dev->driver->preclose(dev, file_priv); 419a85cb24fSFrançois Tigeot 420a85cb24fSFrançois Tigeot /* ======================================================== 421a85cb24fSFrançois Tigeot * Begin inline drm_release 422a85cb24fSFrançois Tigeot */ 423a85cb24fSFrançois Tigeot 4243f2dd94aSFrançois Tigeot DRM_DEBUG("pid = %d, device = 0x%p, open_count = %d\n", 4253f2dd94aSFrançois Tigeot curproc->p_pid, 4263f2dd94aSFrançois Tigeot dev, 4273f2dd94aSFrançois Tigeot dev->open_count); 428a85cb24fSFrançois Tigeot 429a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY)) 430a85cb24fSFrançois Tigeot drm_legacy_lock_release(dev, filp); 431a85cb24fSFrançois Tigeot 432a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 433a85cb24fSFrançois Tigeot drm_legacy_reclaim_buffers(dev, file_priv); 434a85cb24fSFrançois Tigeot 435a85cb24fSFrançois Tigeot drm_events_release(file_priv); 436a85cb24fSFrançois Tigeot 437a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_MODESET)) { 438a85cb24fSFrançois Tigeot drm_fb_release(file_priv); 439a85cb24fSFrançois Tigeot drm_property_destroy_user_blobs(dev, file_priv); 440a85cb24fSFrançois Tigeot } 441a85cb24fSFrançois Tigeot 4423f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 4433f2dd94aSFrançois Tigeot drm_syncobj_release(file_priv); 4443f2dd94aSFrançois Tigeot 445a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 446a85cb24fSFrançois Tigeot drm_gem_release(dev, file_priv); 447a85cb24fSFrançois Tigeot 448a85cb24fSFrançois Tigeot drm_legacy_ctxbitmap_flush(dev, file_priv); 449a85cb24fSFrançois Tigeot 450a85cb24fSFrançois Tigeot if (drm_is_primary_client(file_priv)) 451a85cb24fSFrançois Tigeot drm_master_release(file_priv); 452a85cb24fSFrançois Tigeot 453a85cb24fSFrançois Tigeot if (dev->driver->postclose) 454a85cb24fSFrançois Tigeot dev->driver->postclose(dev, file_priv); 455a85cb24fSFrançois Tigeot 456a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 457a85cb24fSFrançois Tigeot drm_prime_destroy_file_private(&file_priv->prime); 458a85cb24fSFrançois Tigeot 459a85cb24fSFrançois Tigeot WARN_ON(!list_empty(&file_priv->event_list)); 460a85cb24fSFrançois Tigeot 461a85cb24fSFrançois Tigeot put_pid(file_priv->pid); 462a85cb24fSFrançois Tigeot kfree(file_priv); 463a85cb24fSFrançois Tigeot 464a85cb24fSFrançois Tigeot /* ======================================================== 465a85cb24fSFrançois Tigeot * End inline drm_release 466a85cb24fSFrançois Tigeot */ 467a85cb24fSFrançois Tigeot 468a85cb24fSFrançois Tigeot if (!--dev->open_count) { 469a85cb24fSFrançois Tigeot drm_lastclose(dev); 470a85cb24fSFrançois Tigeot #if 0 /* XXX: drm_put_dev() not implemented */ 4713f2dd94aSFrançois Tigeot if (drm_dev_is_unplugged(dev)) 472a85cb24fSFrançois Tigeot drm_put_dev(dev); 473a85cb24fSFrançois Tigeot #endif 474a85cb24fSFrançois Tigeot } 475a85cb24fSFrançois Tigeot mutex_unlock(&drm_global_mutex); 476a85cb24fSFrançois Tigeot 477a85cb24fSFrançois Tigeot drm_minor_release(minor); 478a85cb24fSFrançois Tigeot 479a85cb24fSFrançois Tigeot return 0; 480a85cb24fSFrançois Tigeot } 481a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_release); 482a85cb24fSFrançois Tigeot 483a85cb24fSFrançois Tigeot /** 484a85cb24fSFrançois Tigeot * drm_read - read method for DRM file 485a85cb24fSFrançois Tigeot * @filp: file pointer 486a85cb24fSFrançois Tigeot * @buffer: userspace destination pointer for the read 487a85cb24fSFrançois Tigeot * @count: count in bytes to read 488a85cb24fSFrançois Tigeot * @offset: offset to read 489a85cb24fSFrançois Tigeot * 4903f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.read 491a85cb24fSFrançois Tigeot * method iff they use DRM events for asynchronous signalling to userspace. 492a85cb24fSFrançois Tigeot * Since events are used by the KMS API for vblank and page flip completion this 493a85cb24fSFrançois Tigeot * means all modern display drivers must use it. 494a85cb24fSFrançois Tigeot * 4953f2dd94aSFrançois Tigeot * @offset is ignored, DRM events are read like a pipe. Therefore drivers also 4963f2dd94aSFrançois Tigeot * must set the &file_operation.llseek to no_llseek(). Polling support is 497a85cb24fSFrançois Tigeot * provided by drm_poll(). 498a85cb24fSFrançois Tigeot * 499a85cb24fSFrançois Tigeot * This function will only ever read a full event. Therefore userspace must 500a85cb24fSFrançois Tigeot * supply a big enough buffer to fit any event to ensure forward progress. Since 501a85cb24fSFrançois Tigeot * the maximum event space is currently 4K it's recommended to just use that for 502a85cb24fSFrançois Tigeot * safety. 503a85cb24fSFrançois Tigeot * 504a85cb24fSFrançois Tigeot * RETURNS: 505a85cb24fSFrançois Tigeot * 506a85cb24fSFrançois Tigeot * Number of bytes read (always aligned to full events, and can be 0) or a 507a85cb24fSFrançois Tigeot * negative error code on failure. 508a85cb24fSFrançois Tigeot */ 509a85cb24fSFrançois Tigeot /* 510a85cb24fSFrançois Tigeot ssize_t drm_read(struct file *filp, char __user *buffer, 511a85cb24fSFrançois Tigeot size_t count, loff_t *offset) 512a85cb24fSFrançois Tigeot */ 513a85cb24fSFrançois Tigeot int drm_read(struct dev_read_args *ap) 514a85cb24fSFrançois Tigeot { 515a85cb24fSFrançois Tigeot struct file *filp = ap->a_fp; 516a85cb24fSFrançois Tigeot struct uio *uio = ap->a_uio; 517a85cb24fSFrançois Tigeot size_t count = uio->uio_resid; 518a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 5193f2dd94aSFrançois Tigeot struct drm_device *dev = file_priv->minor->dev; 520a85cb24fSFrançois Tigeot int ret = 0; /* drm_read() returns int in DragonFly */ 521a85cb24fSFrançois Tigeot 522a85cb24fSFrançois Tigeot ret = mutex_lock_interruptible(&file_priv->event_read_lock); 523a85cb24fSFrançois Tigeot if (ret) 524a85cb24fSFrançois Tigeot return ret; 525a85cb24fSFrançois Tigeot 526a85cb24fSFrançois Tigeot for (;;) { 527a85cb24fSFrançois Tigeot struct drm_pending_event *e = NULL; 528a85cb24fSFrançois Tigeot 529a85cb24fSFrançois Tigeot spin_lock_irq(&dev->event_lock); 530a85cb24fSFrançois Tigeot if (!list_empty(&file_priv->event_list)) { 531a85cb24fSFrançois Tigeot e = list_first_entry(&file_priv->event_list, 532a85cb24fSFrançois Tigeot struct drm_pending_event, link); 533a85cb24fSFrançois Tigeot file_priv->event_space += e->event->length; 534a85cb24fSFrançois Tigeot list_del(&e->link); 535a85cb24fSFrançois Tigeot } 536a85cb24fSFrançois Tigeot spin_unlock_irq(&dev->event_lock); 537a85cb24fSFrançois Tigeot 538a85cb24fSFrançois Tigeot if (e == NULL) { 539a85cb24fSFrançois Tigeot if (ret) { 540a85cb24fSFrançois Tigeot ret = 0; /* DragonFly expects a zero return value on success */ 541a85cb24fSFrançois Tigeot break; 542a85cb24fSFrançois Tigeot } 543a85cb24fSFrançois Tigeot 544a85cb24fSFrançois Tigeot if (filp->f_flag & O_NONBLOCK) { 545a85cb24fSFrançois Tigeot ret = -EAGAIN; 546a85cb24fSFrançois Tigeot break; 547a85cb24fSFrançois Tigeot } 548a85cb24fSFrançois Tigeot 549a85cb24fSFrançois Tigeot mutex_unlock(&file_priv->event_read_lock); 550a85cb24fSFrançois Tigeot ret = wait_event_interruptible(file_priv->event_wait, 551a85cb24fSFrançois Tigeot !list_empty(&file_priv->event_list)); 552a85cb24fSFrançois Tigeot if (ret >= 0) 553a85cb24fSFrançois Tigeot ret = mutex_lock_interruptible(&file_priv->event_read_lock); 554a85cb24fSFrançois Tigeot if (ret) 555a85cb24fSFrançois Tigeot return ret; 556a85cb24fSFrançois Tigeot } else { 557a85cb24fSFrançois Tigeot unsigned length = e->event->length; 558a85cb24fSFrançois Tigeot 559a85cb24fSFrançois Tigeot if (length > count - ret) { 560a85cb24fSFrançois Tigeot put_back_event: 561a85cb24fSFrançois Tigeot spin_lock_irq(&dev->event_lock); 562a85cb24fSFrançois Tigeot file_priv->event_space -= length; 563a85cb24fSFrançois Tigeot list_add(&e->link, &file_priv->event_list); 564a85cb24fSFrançois Tigeot spin_unlock_irq(&dev->event_lock); 565a85cb24fSFrançois Tigeot break; 566a85cb24fSFrançois Tigeot } 567a85cb24fSFrançois Tigeot 568a85cb24fSFrançois Tigeot if (uiomove((caddr_t)e->event, length, uio)) { 569a85cb24fSFrançois Tigeot if (ret == 0) 570a85cb24fSFrançois Tigeot ret = -EFAULT; 571a85cb24fSFrançois Tigeot goto put_back_event; 572a85cb24fSFrançois Tigeot } 573a85cb24fSFrançois Tigeot 574a85cb24fSFrançois Tigeot ret += length; 575a85cb24fSFrançois Tigeot kfree(e); 576a85cb24fSFrançois Tigeot } 577a85cb24fSFrançois Tigeot } 578a85cb24fSFrançois Tigeot mutex_unlock(&file_priv->event_read_lock); 579a85cb24fSFrançois Tigeot 580a85cb24fSFrançois Tigeot return ret; 581a85cb24fSFrançois Tigeot } 582a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_read); 583a85cb24fSFrançois Tigeot 584a85cb24fSFrançois Tigeot /** 585a85cb24fSFrançois Tigeot * drm_poll - poll method for DRM file 586a85cb24fSFrançois Tigeot * @filp: file pointer 587a85cb24fSFrançois Tigeot * @wait: poll waiter table 588a85cb24fSFrançois Tigeot * 5893f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.read method 5903f2dd94aSFrançois Tigeot * iff they use DRM events for asynchronous signalling to userspace. Since 5913f2dd94aSFrançois Tigeot * events are used by the KMS API for vblank and page flip completion this means 5923f2dd94aSFrançois Tigeot * all modern display drivers must use it. 593a85cb24fSFrançois Tigeot * 594a85cb24fSFrançois Tigeot * See also drm_read(). 595a85cb24fSFrançois Tigeot * 596a85cb24fSFrançois Tigeot * RETURNS: 597a85cb24fSFrançois Tigeot * 598a85cb24fSFrançois Tigeot * Mask of POLL flags indicating the current status of the file. 599a85cb24fSFrançois Tigeot */ 600a85cb24fSFrançois Tigeot static int 601a85cb24fSFrançois Tigeot drmfilt(struct knote *kn, long hint) 602a85cb24fSFrançois Tigeot { 603a85cb24fSFrançois Tigeot struct drm_file *file_priv = (struct drm_file *)kn->kn_hook; 604a85cb24fSFrançois Tigeot int ready = 0; 605a85cb24fSFrançois Tigeot 606a85cb24fSFrançois Tigeot // poll_wait(filp, &file_priv->event_wait, wait); 607a85cb24fSFrançois Tigeot 608a85cb24fSFrançois Tigeot if (!list_empty(&file_priv->event_list)) 609a85cb24fSFrançois Tigeot ready = 1; 610a85cb24fSFrançois Tigeot 611a85cb24fSFrançois Tigeot return (ready); 612a85cb24fSFrançois Tigeot } 613a85cb24fSFrançois Tigeot 614a85cb24fSFrançois Tigeot static void 615a85cb24fSFrançois Tigeot drmfilt_detach(struct knote *kn) 616a85cb24fSFrançois Tigeot { 617a85cb24fSFrançois Tigeot struct drm_file *file_priv; 618a85cb24fSFrançois Tigeot struct klist *klist; 619a85cb24fSFrançois Tigeot 620a85cb24fSFrançois Tigeot file_priv = (struct drm_file *)kn->kn_hook; 621a85cb24fSFrançois Tigeot 622a85cb24fSFrançois Tigeot klist = &file_priv->dkq.ki_note; 623a85cb24fSFrançois Tigeot knote_remove(klist, kn); 624a85cb24fSFrançois Tigeot } 625a85cb24fSFrançois Tigeot 626a85cb24fSFrançois Tigeot static struct filterops drmfiltops = 627a85cb24fSFrançois Tigeot { FILTEROP_MPSAFE | FILTEROP_ISFD, NULL, drmfilt_detach, drmfilt }; 628a85cb24fSFrançois Tigeot 629a85cb24fSFrançois Tigeot int 630a85cb24fSFrançois Tigeot drm_kqfilter(struct dev_kqfilter_args *ap) 631a85cb24fSFrançois Tigeot { 632a85cb24fSFrançois Tigeot struct file *filp = ap->a_fp; 633a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 634a85cb24fSFrançois Tigeot struct knote *kn = ap->a_kn; 635a85cb24fSFrançois Tigeot struct klist *klist; 636a85cb24fSFrançois Tigeot 637a85cb24fSFrançois Tigeot ap->a_result = 0; 638a85cb24fSFrançois Tigeot 639a85cb24fSFrançois Tigeot switch (kn->kn_filter) { 640a85cb24fSFrançois Tigeot case EVFILT_READ: 641a85cb24fSFrançois Tigeot case EVFILT_WRITE: 642a85cb24fSFrançois Tigeot kn->kn_fop = &drmfiltops; 643a85cb24fSFrançois Tigeot kn->kn_hook = (caddr_t)file_priv; 644a85cb24fSFrançois Tigeot break; 645a85cb24fSFrançois Tigeot default: 646a85cb24fSFrançois Tigeot ap->a_result = EOPNOTSUPP; 647a85cb24fSFrançois Tigeot return (0); 648a85cb24fSFrançois Tigeot } 649a85cb24fSFrançois Tigeot 650a85cb24fSFrançois Tigeot klist = &file_priv->dkq.ki_note; 651a85cb24fSFrançois Tigeot knote_insert(klist, kn); 652a85cb24fSFrançois Tigeot 653a85cb24fSFrançois Tigeot return (0); 654a85cb24fSFrançois Tigeot } 655a85cb24fSFrançois Tigeot 656a85cb24fSFrançois Tigeot /** 657a85cb24fSFrançois Tigeot * drm_event_reserve_init_locked - init a DRM event and reserve space for it 658a85cb24fSFrançois Tigeot * @dev: DRM device 659a85cb24fSFrançois Tigeot * @file_priv: DRM file private data 660a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 661a85cb24fSFrançois Tigeot * @e: actual event data to deliver to userspace 662a85cb24fSFrançois Tigeot * 663a85cb24fSFrançois Tigeot * This function prepares the passed in event for eventual delivery. If the event 664a85cb24fSFrançois Tigeot * doesn't get delivered (because the IOCTL fails later on, before queuing up 665a85cb24fSFrançois Tigeot * anything) then the even must be cancelled and freed using 666a85cb24fSFrançois Tigeot * drm_event_cancel_free(). Successfully initialized events should be sent out 667a85cb24fSFrançois Tigeot * using drm_send_event() or drm_send_event_locked() to signal completion of the 668a85cb24fSFrançois Tigeot * asynchronous event to userspace. 669a85cb24fSFrançois Tigeot * 670a85cb24fSFrançois Tigeot * If callers embedded @p into a larger structure it must be allocated with 671a85cb24fSFrançois Tigeot * kmalloc and @p must be the first member element. 672a85cb24fSFrançois Tigeot * 673a85cb24fSFrançois Tigeot * This is the locked version of drm_event_reserve_init() for callers which 674a85cb24fSFrançois Tigeot * already hold &drm_device.event_lock. 675a85cb24fSFrançois Tigeot * 676a85cb24fSFrançois Tigeot * RETURNS: 677a85cb24fSFrançois Tigeot * 678a85cb24fSFrançois Tigeot * 0 on success or a negative error code on failure. 679a85cb24fSFrançois Tigeot */ 680a85cb24fSFrançois Tigeot int drm_event_reserve_init_locked(struct drm_device *dev, 681a85cb24fSFrançois Tigeot struct drm_file *file_priv, 682a85cb24fSFrançois Tigeot struct drm_pending_event *p, 683a85cb24fSFrançois Tigeot struct drm_event *e) 684a85cb24fSFrançois Tigeot { 685a85cb24fSFrançois Tigeot if (file_priv->event_space < e->length) 686a85cb24fSFrançois Tigeot return -ENOMEM; 687a85cb24fSFrançois Tigeot 688a85cb24fSFrançois Tigeot file_priv->event_space -= e->length; 689a85cb24fSFrançois Tigeot 690a85cb24fSFrançois Tigeot p->event = e; 691a85cb24fSFrançois Tigeot list_add(&p->pending_link, &file_priv->pending_event_list); 692a85cb24fSFrançois Tigeot p->file_priv = file_priv; 693a85cb24fSFrançois Tigeot 694a85cb24fSFrançois Tigeot return 0; 695a85cb24fSFrançois Tigeot } 696a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_reserve_init_locked); 697a85cb24fSFrançois Tigeot 698a85cb24fSFrançois Tigeot /** 699a85cb24fSFrançois Tigeot * drm_event_reserve_init - init a DRM event and reserve space for it 700a85cb24fSFrançois Tigeot * @dev: DRM device 701a85cb24fSFrançois Tigeot * @file_priv: DRM file private data 702a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 703a85cb24fSFrançois Tigeot * @e: actual event data to deliver to userspace 704a85cb24fSFrançois Tigeot * 705a85cb24fSFrançois Tigeot * This function prepares the passed in event for eventual delivery. If the event 706a85cb24fSFrançois Tigeot * doesn't get delivered (because the IOCTL fails later on, before queuing up 707a85cb24fSFrançois Tigeot * anything) then the even must be cancelled and freed using 708a85cb24fSFrançois Tigeot * drm_event_cancel_free(). Successfully initialized events should be sent out 709a85cb24fSFrançois Tigeot * using drm_send_event() or drm_send_event_locked() to signal completion of the 710a85cb24fSFrançois Tigeot * asynchronous event to userspace. 711a85cb24fSFrançois Tigeot * 712a85cb24fSFrançois Tigeot * If callers embedded @p into a larger structure it must be allocated with 713a85cb24fSFrançois Tigeot * kmalloc and @p must be the first member element. 714a85cb24fSFrançois Tigeot * 715a85cb24fSFrançois Tigeot * Callers which already hold &drm_device.event_lock should use 716a85cb24fSFrançois Tigeot * drm_event_reserve_init_locked() instead. 717a85cb24fSFrançois Tigeot * 718a85cb24fSFrançois Tigeot * RETURNS: 719a85cb24fSFrançois Tigeot * 720a85cb24fSFrançois Tigeot * 0 on success or a negative error code on failure. 721a85cb24fSFrançois Tigeot */ 722a85cb24fSFrançois Tigeot int drm_event_reserve_init(struct drm_device *dev, 723a85cb24fSFrançois Tigeot struct drm_file *file_priv, 724a85cb24fSFrançois Tigeot struct drm_pending_event *p, 725a85cb24fSFrançois Tigeot struct drm_event *e) 726a85cb24fSFrançois Tigeot { 727a85cb24fSFrançois Tigeot unsigned long flags; 728a85cb24fSFrançois Tigeot int ret; 729a85cb24fSFrançois Tigeot 730a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 731a85cb24fSFrançois Tigeot ret = drm_event_reserve_init_locked(dev, file_priv, p, e); 732a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 733a85cb24fSFrançois Tigeot 734a85cb24fSFrançois Tigeot return ret; 735a85cb24fSFrançois Tigeot } 736a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_reserve_init); 737a85cb24fSFrançois Tigeot 738a85cb24fSFrançois Tigeot /** 739a85cb24fSFrançois Tigeot * drm_event_cancel_free - free a DRM event and release it's space 740a85cb24fSFrançois Tigeot * @dev: DRM device 741a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 742a85cb24fSFrançois Tigeot * 743a85cb24fSFrançois Tigeot * This function frees the event @p initialized with drm_event_reserve_init() 7443f2dd94aSFrançois Tigeot * and releases any allocated space. It is used to cancel an event when the 7453f2dd94aSFrançois Tigeot * nonblocking operation could not be submitted and needed to be aborted. 746a85cb24fSFrançois Tigeot */ 747a85cb24fSFrançois Tigeot void drm_event_cancel_free(struct drm_device *dev, 748a85cb24fSFrançois Tigeot struct drm_pending_event *p) 749a85cb24fSFrançois Tigeot { 750a85cb24fSFrançois Tigeot unsigned long flags; 751a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 752a85cb24fSFrançois Tigeot if (p->file_priv) { 753a85cb24fSFrançois Tigeot p->file_priv->event_space += p->event->length; 754a85cb24fSFrançois Tigeot list_del(&p->pending_link); 755a85cb24fSFrançois Tigeot } 756a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 7573f2dd94aSFrançois Tigeot 7583f2dd94aSFrançois Tigeot if (p->fence) 7593f2dd94aSFrançois Tigeot dma_fence_put(p->fence); 7603f2dd94aSFrançois Tigeot 761a85cb24fSFrançois Tigeot kfree(p); 762a85cb24fSFrançois Tigeot } 763a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_cancel_free); 764a85cb24fSFrançois Tigeot 765a85cb24fSFrançois Tigeot /** 766a85cb24fSFrançois Tigeot * drm_send_event_locked - send DRM event to file descriptor 767a85cb24fSFrançois Tigeot * @dev: DRM device 768a85cb24fSFrançois Tigeot * @e: DRM event to deliver 769a85cb24fSFrançois Tigeot * 770a85cb24fSFrançois Tigeot * This function sends the event @e, initialized with drm_event_reserve_init(), 771a85cb24fSFrançois Tigeot * to its associated userspace DRM file. Callers must already hold 772a85cb24fSFrançois Tigeot * &drm_device.event_lock, see drm_send_event() for the unlocked version. 773a85cb24fSFrançois Tigeot * 774a85cb24fSFrançois Tigeot * Note that the core will take care of unlinking and disarming events when the 775a85cb24fSFrançois Tigeot * corresponding DRM file is closed. Drivers need not worry about whether the 776a85cb24fSFrançois Tigeot * DRM file for this event still exists and can call this function upon 777a85cb24fSFrançois Tigeot * completion of the asynchronous work unconditionally. 778a85cb24fSFrançois Tigeot */ 779a85cb24fSFrançois Tigeot void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) 780a85cb24fSFrançois Tigeot { 781a85cb24fSFrançois Tigeot assert_spin_locked(&dev->event_lock); 782a85cb24fSFrançois Tigeot 783a85cb24fSFrançois Tigeot if (e->completion) { 784a85cb24fSFrançois Tigeot complete_all(e->completion); 785a85cb24fSFrançois Tigeot e->completion_release(e->completion); 786a85cb24fSFrançois Tigeot e->completion = NULL; 787a85cb24fSFrançois Tigeot } 788a85cb24fSFrançois Tigeot 789a85cb24fSFrançois Tigeot if (e->fence) { 790a85cb24fSFrançois Tigeot dma_fence_signal(e->fence); 791a85cb24fSFrançois Tigeot dma_fence_put(e->fence); 792a85cb24fSFrançois Tigeot } 793a85cb24fSFrançois Tigeot 794a85cb24fSFrançois Tigeot if (!e->file_priv) { 795a85cb24fSFrançois Tigeot kfree(e); 796a85cb24fSFrançois Tigeot return; 797a85cb24fSFrançois Tigeot } 798a85cb24fSFrançois Tigeot 799a85cb24fSFrançois Tigeot list_del(&e->pending_link); 800a85cb24fSFrançois Tigeot list_add_tail(&e->link, 801a85cb24fSFrançois Tigeot &e->file_priv->event_list); 802a85cb24fSFrançois Tigeot wake_up_interruptible(&e->file_priv->event_wait); 803a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 804a85cb24fSFrançois Tigeot KNOTE(&e->file_priv->dkq.ki_note, 0); 805a85cb24fSFrançois Tigeot #endif 806a85cb24fSFrançois Tigeot } 807a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_send_event_locked); 808a85cb24fSFrançois Tigeot 809a85cb24fSFrançois Tigeot /** 810a85cb24fSFrançois Tigeot * drm_send_event - send DRM event to file descriptor 811a85cb24fSFrançois Tigeot * @dev: DRM device 812a85cb24fSFrançois Tigeot * @e: DRM event to deliver 813a85cb24fSFrançois Tigeot * 814a85cb24fSFrançois Tigeot * This function sends the event @e, initialized with drm_event_reserve_init(), 815a85cb24fSFrançois Tigeot * to its associated userspace DRM file. This function acquires 816a85cb24fSFrançois Tigeot * &drm_device.event_lock, see drm_send_event_locked() for callers which already 817a85cb24fSFrançois Tigeot * hold this lock. 818a85cb24fSFrançois Tigeot * 819a85cb24fSFrançois Tigeot * Note that the core will take care of unlinking and disarming events when the 820a85cb24fSFrançois Tigeot * corresponding DRM file is closed. Drivers need not worry about whether the 821a85cb24fSFrançois Tigeot * DRM file for this event still exists and can call this function upon 822a85cb24fSFrançois Tigeot * completion of the asynchronous work unconditionally. 823a85cb24fSFrançois Tigeot */ 824a85cb24fSFrançois Tigeot void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) 825a85cb24fSFrançois Tigeot { 826a85cb24fSFrançois Tigeot unsigned long irqflags; 827a85cb24fSFrançois Tigeot 828a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, irqflags); 829a85cb24fSFrançois Tigeot drm_send_event_locked(dev, e); 830a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, irqflags); 831a85cb24fSFrançois Tigeot } 832a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_send_event); 833