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 56*3f2dd94aSFrançois Tigeot * implemented in the DRM core. The resulting &struct file_operations must be 57*3f2dd94aSFranç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 59*3f2dd94aSFrançois Tigeot * Note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n, so there's no 60*3f2dd94aSFrançois Tigeot * need to sprinkle #ifdef into the code. Drivers which implement private ioctls 61*3f2dd94aSFrançois Tigeot * that require 32/64 bit compatibility support must provide their own 62*3f2dd94aSFrançois Tigeot * &file_operations.compat_ioctl handler that processes private ioctls and calls 63*3f2dd94aSFranç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 * 71*3f2dd94aSFrançois Tigeot * For the driver-side event interface see drm_event_reserve_init() and 72*3f2dd94aSFrançois Tigeot * drm_send_event() as the main starting points. 73*3f2dd94aSFranç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 77*3f2dd94aSFrançois Tigeot * specific implementations. For GEM-based drivers this is drm_gem_mmap(), and 78*3f2dd94aSFranç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 81*3f2dd94aSFranç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 * }; 94*3f2dd94aSFrançois Tigeot * 95*3f2dd94aSFrançois Tigeot * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for 96*3f2dd94aSFrançois Tigeot * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this 97*3f2dd94aSFrançois Tigeot * simpler. 98*3f2dd94aSFrançois Tigeot * 99*3f2dd94aSFrançois Tigeot * The driver's &file_operations must be stored in &drm_driver.fops. 100*3f2dd94aSFrançois Tigeot * 101*3f2dd94aSFrançois Tigeot * For driver-private IOCTL handling see the more detailed discussion in 102*3f2dd94aSFrançois Tigeot * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`. 103a85cb24fSFrançois Tigeot */ 104a85cb24fSFrançois Tigeot 105*3f2dd94aSFrançois Tigeot static int drm_open_helper(struct cdev *kdev, int flags, 106*3f2dd94aSFranç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 * 133*3f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.open method. 134*3f2dd94aSFrançois Tigeot * It looks up the correct DRM device and instantiates all the per-file 135*3f2dd94aSFranç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 { 145*3f2dd94aSFrançois Tigeot #ifdef __DragonFly__ 146a85cb24fSFrançois Tigeot struct file *filp = ap->a_fp; 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; 150*3f2dd94aSFrançois Tigeot #endif 151*3f2dd94aSFrançois Tigeot struct drm_device *dev; 152*3f2dd94aSFranç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)); 157*3f2dd94aSFrançois Tigeot if (IS_ERR(minor)) 158*3f2dd94aSFrançois Tigeot return PTR_ERR(minor); 159*3f2dd94aSFrançois Tigeot 160*3f2dd94aSFranç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*3f2dd94aSFrançois Tigeot retcode = drm_open_helper(kdev, flags, ap->a_fp, minor); 170*3f2dd94aSFrançois Tigeot if (retcode) 171*3f2dd94aSFrançois Tigeot goto err_undo; 172a85cb24fSFrançois Tigeot if (need_setup) { 173a85cb24fSFrançois Tigeot retcode = drm_setup(dev); 174a85cb24fSFrançois Tigeot if (retcode) 175a85cb24fSFrançois Tigeot goto err_undo; 176a85cb24fSFrançois Tigeot } 177*3f2dd94aSFrançois Tigeot #ifdef __DragonFly__ 178*3f2dd94aSFrançois Tigeot device_busy(dev->dev->bsddev); 179*3f2dd94aSFrançois Tigeot #endif 180a85cb24fSFrançois Tigeot return 0; 181a85cb24fSFrançois Tigeot 182a85cb24fSFrançois Tigeot err_undo: 183a85cb24fSFrançois Tigeot dev->open_count--; 184a85cb24fSFrançois Tigeot drm_minor_release(minor); 185a85cb24fSFrançois Tigeot return retcode; 186a85cb24fSFrançois Tigeot } 187a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_open); 188a85cb24fSFrançois Tigeot 189a85cb24fSFrançois Tigeot /* 190a85cb24fSFrançois Tigeot * Check whether DRI will run on this CPU. 191a85cb24fSFrançois Tigeot * 192a85cb24fSFrançois Tigeot * \return non-zero if the DRI will run on this CPU, or zero otherwise. 193a85cb24fSFrançois Tigeot */ 194*3f2dd94aSFrançois Tigeot static int drm_cpu_valid(void) 195*3f2dd94aSFrançois Tigeot { 196*3f2dd94aSFrançois Tigeot #if defined(__sparc__) && !defined(__sparc_v9__) 197*3f2dd94aSFrançois Tigeot return 0; /* No cmpxchg before v9 sparc. */ 198*3f2dd94aSFrançois Tigeot #endif 199*3f2dd94aSFrançois Tigeot return 1; 200*3f2dd94aSFrançois Tigeot } 201a85cb24fSFrançois Tigeot 202a85cb24fSFrançois Tigeot /* 203a85cb24fSFrançois Tigeot * Called whenever a process opens /dev/drm. 204a85cb24fSFrançois Tigeot * 205a85cb24fSFrançois Tigeot * \param filp file pointer. 206a85cb24fSFrançois Tigeot * \param minor acquired minor-object. 207a85cb24fSFrançois Tigeot * \return zero on success or a negative number on failure. 208a85cb24fSFrançois Tigeot * 209a85cb24fSFrançois Tigeot * Creates and initializes a drm_file structure for the file private data in \p 210a85cb24fSFrançois Tigeot * filp and add it into the double linked list in \p dev. 211a85cb24fSFrançois Tigeot */ 212*3f2dd94aSFrançois Tigeot static int drm_open_helper(struct cdev *kdev, int flags, 213*3f2dd94aSFrançois Tigeot struct file *filp, struct drm_minor *minor) 214a85cb24fSFrançois Tigeot { 215*3f2dd94aSFrançois Tigeot struct drm_device *dev = minor->dev; 216a85cb24fSFrançois Tigeot struct drm_file *priv; 217a85cb24fSFrançois Tigeot int ret; 218a85cb24fSFrançois Tigeot 219a85cb24fSFrançois Tigeot if (flags & O_EXCL) 220*3f2dd94aSFrançois Tigeot return -EBUSY; /* No exclusive opens */ 221*3f2dd94aSFrançois Tigeot if (!drm_cpu_valid()) 222*3f2dd94aSFrançois Tigeot return -EINVAL; 223a85cb24fSFrançois Tigeot 224*3f2dd94aSFrançois Tigeot DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, minor->index); 225a85cb24fSFrançois Tigeot 226a85cb24fSFrançois Tigeot priv = kzalloc(sizeof(*priv), GFP_KERNEL); 227a85cb24fSFrançois Tigeot if (!priv) 228a85cb24fSFrançois Tigeot return -ENOMEM; 229a85cb24fSFrançois Tigeot 230a85cb24fSFrançois Tigeot filp->private_data = priv; 231a85cb24fSFrançois Tigeot priv->filp = filp; 232*3f2dd94aSFrançois Tigeot priv->pid = curproc->p_pid; 233a85cb24fSFrançois Tigeot priv->minor = minor; 234a85cb24fSFrançois Tigeot priv->dev = dev; 235a85cb24fSFrançois Tigeot 236a85cb24fSFrançois Tigeot /* for compatibility root is always authenticated */ 237a85cb24fSFrançois Tigeot priv->authenticated = capable(CAP_SYS_ADMIN); 238a85cb24fSFrançois Tigeot priv->lock_count = 0; 239a85cb24fSFrançois Tigeot 240a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->lhead); 241a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->fbs); 242a85cb24fSFrançois Tigeot lockinit(&priv->fbs_lock, "dpfl", 0, LK_CANRECURSE); 243a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->blobs); 244a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->pending_event_list); 245a85cb24fSFrançois Tigeot INIT_LIST_HEAD(&priv->event_list); 246a85cb24fSFrançois Tigeot init_waitqueue_head(&priv->event_wait); 247a85cb24fSFrançois Tigeot priv->event_space = 4096; /* set aside 4k for event buffer */ 248a85cb24fSFrançois Tigeot 249a85cb24fSFrançois Tigeot lockinit(&priv->event_read_lock, "dperl", 0, LK_CANRECURSE); 250a85cb24fSFrançois Tigeot 251a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 252a85cb24fSFrançois Tigeot drm_gem_open(dev, priv); 253a85cb24fSFrançois Tigeot 254*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 255*3f2dd94aSFrançois Tigeot drm_syncobj_open(priv); 256*3f2dd94aSFrançois Tigeot 257*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 258*3f2dd94aSFrançois Tigeot drm_prime_init_file_private(&priv->prime); 259*3f2dd94aSFrançois Tigeot 260a85cb24fSFrançois Tigeot if (dev->driver->open) { 261a85cb24fSFrançois Tigeot /* shared code returns -errno */ 262a85cb24fSFrançois Tigeot ret = -dev->driver->open(dev, priv); 263*3f2dd94aSFrançois Tigeot if (ret != 0) 264*3f2dd94aSFrançois Tigeot goto out_prime_destroy; 265a85cb24fSFrançois Tigeot } 266a85cb24fSFrançois Tigeot 267a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 268*3f2dd94aSFrançois Tigeot kdev->si_drv1 = dev; 269a85cb24fSFrançois Tigeot #endif 270a85cb24fSFrançois Tigeot 271*3f2dd94aSFrançois Tigeot if (drm_is_primary_client(priv)) { 272*3f2dd94aSFrançois Tigeot ret = drm_master_open(priv); 273*3f2dd94aSFrançois Tigeot if (ret) 274*3f2dd94aSFrançois Tigeot goto out_close; 275*3f2dd94aSFrançois Tigeot } 276*3f2dd94aSFrançois Tigeot 277a85cb24fSFrançois Tigeot mutex_lock(&dev->filelist_mutex); 278a85cb24fSFrançois Tigeot list_add(&priv->lhead, &dev->filelist); 279a85cb24fSFrançois Tigeot mutex_unlock(&dev->filelist_mutex); 280a85cb24fSFrançois Tigeot 281*3f2dd94aSFrançois Tigeot #ifdef __alpha__ 282*3f2dd94aSFrançois Tigeot /* 283*3f2dd94aSFrançois Tigeot * Default the hose 284*3f2dd94aSFrançois Tigeot */ 285*3f2dd94aSFrançois Tigeot if (!dev->hose) { 286*3f2dd94aSFrançois Tigeot struct pci_dev *pci_dev; 287*3f2dd94aSFrançois Tigeot pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); 288*3f2dd94aSFrançois Tigeot if (pci_dev) { 289*3f2dd94aSFrançois Tigeot dev->hose = pci_dev->sysdata; 290*3f2dd94aSFrançois Tigeot pci_dev_put(pci_dev); 291*3f2dd94aSFrançois Tigeot } 292*3f2dd94aSFrançois Tigeot if (!dev->hose) { 293*3f2dd94aSFrançois Tigeot struct pci_bus *b = list_entry(pci_root_buses.next, 294*3f2dd94aSFrançois Tigeot struct pci_bus, node); 295*3f2dd94aSFrançois Tigeot if (b) 296*3f2dd94aSFrançois Tigeot dev->hose = b->sysdata; 297*3f2dd94aSFrançois Tigeot } 298*3f2dd94aSFrançois Tigeot } 299a85cb24fSFrançois Tigeot #endif 300*3f2dd94aSFrançois Tigeot 301*3f2dd94aSFrançois Tigeot return 0; 302*3f2dd94aSFrançois Tigeot 303*3f2dd94aSFrançois Tigeot out_close: 304a85cb24fSFrançois Tigeot if (dev->driver->postclose) 305a85cb24fSFrançois Tigeot dev->driver->postclose(dev, priv); 306*3f2dd94aSFrançois Tigeot out_prime_destroy: 307*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 308*3f2dd94aSFrançois Tigeot drm_prime_destroy_file_private(&priv->prime); 309*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 310*3f2dd94aSFrançois Tigeot drm_syncobj_release(priv); 311a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 312a85cb24fSFrançois Tigeot drm_gem_release(dev, priv); 313a85cb24fSFrançois Tigeot put_pid(priv->pid); 314a85cb24fSFrançois Tigeot kfree(priv); 315a85cb24fSFrançois Tigeot filp->private_data = NULL; 316a85cb24fSFrançois Tigeot return ret; 317a85cb24fSFrançois Tigeot } 318a85cb24fSFrançois Tigeot 319a85cb24fSFrançois Tigeot static void drm_events_release(struct drm_file *file_priv) 320a85cb24fSFrançois Tigeot { 321a85cb24fSFrançois Tigeot struct drm_device *dev = file_priv->minor->dev; 322a85cb24fSFrançois Tigeot struct drm_pending_event *e, *et; 323a85cb24fSFrançois Tigeot unsigned long flags; 324a85cb24fSFrançois Tigeot 325a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 326a85cb24fSFrançois Tigeot 327a85cb24fSFrançois Tigeot /* Unlink pending events */ 328a85cb24fSFrançois Tigeot list_for_each_entry_safe(e, et, &file_priv->pending_event_list, 329a85cb24fSFrançois Tigeot pending_link) { 330a85cb24fSFrançois Tigeot list_del(&e->pending_link); 331a85cb24fSFrançois Tigeot e->file_priv = NULL; 332a85cb24fSFrançois Tigeot } 333a85cb24fSFrançois Tigeot 334a85cb24fSFrançois Tigeot /* Remove unconsumed events */ 335a85cb24fSFrançois Tigeot list_for_each_entry_safe(e, et, &file_priv->event_list, link) { 336a85cb24fSFrançois Tigeot list_del(&e->link); 337a85cb24fSFrançois Tigeot kfree(e); 338a85cb24fSFrançois Tigeot } 339a85cb24fSFrançois Tigeot 340a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 341a85cb24fSFrançois Tigeot } 342a85cb24fSFrançois Tigeot 343a85cb24fSFrançois Tigeot static void drm_legacy_dev_reinit(struct drm_device *dev) 344a85cb24fSFrançois Tigeot { 345a85cb24fSFrançois Tigeot if (dev->irq_enabled) 346a85cb24fSFrançois Tigeot drm_irq_uninstall(dev); 347a85cb24fSFrançois Tigeot 348a85cb24fSFrançois Tigeot mutex_lock(&dev->struct_mutex); 349a85cb24fSFrançois Tigeot 350a85cb24fSFrançois Tigeot drm_legacy_agp_clear(dev); 351a85cb24fSFrançois Tigeot 352a85cb24fSFrançois Tigeot drm_legacy_sg_cleanup(dev); 353a85cb24fSFrançois Tigeot drm_legacy_vma_flush(dev); 354a85cb24fSFrançois Tigeot drm_legacy_dma_takedown(dev); 355a85cb24fSFrançois Tigeot 356a85cb24fSFrançois Tigeot mutex_unlock(&dev->struct_mutex); 357a85cb24fSFrançois Tigeot 358a85cb24fSFrançois Tigeot dev->sigdata.lock = NULL; 359a85cb24fSFrançois Tigeot 360a85cb24fSFrançois Tigeot dev->context_flag = 0; 361a85cb24fSFrançois Tigeot dev->last_context = 0; 362a85cb24fSFrançois Tigeot dev->if_version = 0; 363a85cb24fSFrançois Tigeot 364a85cb24fSFrançois Tigeot DRM_DEBUG("lastclose completed\n"); 365a85cb24fSFrançois Tigeot } 366a85cb24fSFrançois Tigeot 367a85cb24fSFrançois Tigeot void drm_lastclose(struct drm_device * dev) 368a85cb24fSFrançois Tigeot { 369a85cb24fSFrançois Tigeot DRM_DEBUG("\n"); 370a85cb24fSFrançois Tigeot 371a85cb24fSFrançois Tigeot if (dev->driver->lastclose) 372a85cb24fSFrançois Tigeot dev->driver->lastclose(dev); 373a85cb24fSFrançois Tigeot DRM_DEBUG("driver lastclose completed\n"); 374a85cb24fSFrançois Tigeot 375a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY)) 376a85cb24fSFrançois Tigeot drm_legacy_dev_reinit(dev); 377a85cb24fSFrançois Tigeot } 378a85cb24fSFrançois Tigeot 379a85cb24fSFrançois Tigeot /** 380a85cb24fSFrançois Tigeot * drm_release - release method for DRM file 381a85cb24fSFrançois Tigeot * @inode: device inode 382a85cb24fSFrançois Tigeot * @filp: file pointer. 383a85cb24fSFrançois Tigeot * 384*3f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.release 385*3f2dd94aSFrançois Tigeot * method. It frees any resources associated with the open file, and calls the 386*3f2dd94aSFrançois Tigeot * &drm_driver.postclose driver callback. If this is the last open file for the 387*3f2dd94aSFrançois Tigeot * DRM device also proceeds to call the &drm_driver.lastclose driver callback. 388a85cb24fSFrançois Tigeot * 389a85cb24fSFrançois Tigeot * RETURNS: 390a85cb24fSFrançois Tigeot * 391a85cb24fSFrançois Tigeot * Always succeeds and returns 0. 392a85cb24fSFrançois Tigeot */ 393a85cb24fSFrançois Tigeot int drm_release(struct inode *inode, struct file *filp) 394a85cb24fSFrançois Tigeot { 395a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 396a85cb24fSFrançois Tigeot struct drm_minor *minor = file_priv->minor; 397a85cb24fSFrançois Tigeot struct drm_device *dev = minor->dev; 398a85cb24fSFrançois Tigeot 399a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 400a85cb24fSFrançois Tigeot /* dev is not correctly set yet */ 401a85cb24fSFrançois Tigeot return 0; 402a85cb24fSFrançois Tigeot #endif 403a85cb24fSFrançois Tigeot 404a85cb24fSFrançois Tigeot mutex_lock(&drm_global_mutex); 405a85cb24fSFrançois Tigeot 406a85cb24fSFrançois Tigeot DRM_DEBUG("open_count = %d\n", dev->open_count); 407a85cb24fSFrançois Tigeot 408a85cb24fSFrançois Tigeot mutex_lock(&dev->filelist_mutex); 409a85cb24fSFrançois Tigeot list_del(&file_priv->lhead); 410a85cb24fSFrançois Tigeot mutex_unlock(&dev->filelist_mutex); 411a85cb24fSFrançois Tigeot 412*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY) && 413*3f2dd94aSFrançois Tigeot dev->driver->preclose) 414a85cb24fSFrançois Tigeot dev->driver->preclose(dev, file_priv); 415a85cb24fSFrançois Tigeot 416a85cb24fSFrançois Tigeot /* ======================================================== 417a85cb24fSFrançois Tigeot * Begin inline drm_release 418a85cb24fSFrançois Tigeot */ 419a85cb24fSFrançois Tigeot 420*3f2dd94aSFrançois Tigeot DRM_DEBUG("pid = %d, device = 0x%p, open_count = %d\n", 421*3f2dd94aSFrançois Tigeot curproc->p_pid, 422*3f2dd94aSFrançois Tigeot dev, 423*3f2dd94aSFrançois Tigeot dev->open_count); 424a85cb24fSFrançois Tigeot 425a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_LEGACY)) 426a85cb24fSFrançois Tigeot drm_legacy_lock_release(dev, filp); 427a85cb24fSFrançois Tigeot 428a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 429a85cb24fSFrançois Tigeot drm_legacy_reclaim_buffers(dev, file_priv); 430a85cb24fSFrançois Tigeot 431a85cb24fSFrançois Tigeot drm_events_release(file_priv); 432a85cb24fSFrançois Tigeot 433a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_MODESET)) { 434a85cb24fSFrançois Tigeot drm_fb_release(file_priv); 435a85cb24fSFrançois Tigeot drm_property_destroy_user_blobs(dev, file_priv); 436a85cb24fSFrançois Tigeot } 437a85cb24fSFrançois Tigeot 438*3f2dd94aSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 439*3f2dd94aSFrançois Tigeot drm_syncobj_release(file_priv); 440*3f2dd94aSFrançois Tigeot 441a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_GEM)) 442a85cb24fSFrançois Tigeot drm_gem_release(dev, file_priv); 443a85cb24fSFrançois Tigeot 444a85cb24fSFrançois Tigeot drm_legacy_ctxbitmap_flush(dev, file_priv); 445a85cb24fSFrançois Tigeot 446a85cb24fSFrançois Tigeot if (drm_is_primary_client(file_priv)) 447a85cb24fSFrançois Tigeot drm_master_release(file_priv); 448a85cb24fSFrançois Tigeot 449a85cb24fSFrançois Tigeot if (dev->driver->postclose) 450a85cb24fSFrançois Tigeot dev->driver->postclose(dev, file_priv); 451a85cb24fSFrançois Tigeot 452a85cb24fSFrançois Tigeot if (drm_core_check_feature(dev, DRIVER_PRIME)) 453a85cb24fSFrançois Tigeot drm_prime_destroy_file_private(&file_priv->prime); 454a85cb24fSFrançois Tigeot 455a85cb24fSFrançois Tigeot WARN_ON(!list_empty(&file_priv->event_list)); 456a85cb24fSFrançois Tigeot 457a85cb24fSFrançois Tigeot put_pid(file_priv->pid); 458a85cb24fSFrançois Tigeot kfree(file_priv); 459a85cb24fSFrançois Tigeot 460a85cb24fSFrançois Tigeot /* ======================================================== 461a85cb24fSFrançois Tigeot * End inline drm_release 462a85cb24fSFrançois Tigeot */ 463a85cb24fSFrançois Tigeot 464a85cb24fSFrançois Tigeot if (!--dev->open_count) { 465a85cb24fSFrançois Tigeot drm_lastclose(dev); 466a85cb24fSFrançois Tigeot #if 0 /* XXX: drm_put_dev() not implemented */ 467*3f2dd94aSFrançois Tigeot if (drm_dev_is_unplugged(dev)) 468a85cb24fSFrançois Tigeot drm_put_dev(dev); 469a85cb24fSFrançois Tigeot #endif 470a85cb24fSFrançois Tigeot } 471a85cb24fSFrançois Tigeot mutex_unlock(&drm_global_mutex); 472a85cb24fSFrançois Tigeot 473a85cb24fSFrançois Tigeot drm_minor_release(minor); 474a85cb24fSFrançois Tigeot 475a85cb24fSFrançois Tigeot return 0; 476a85cb24fSFrançois Tigeot } 477a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_release); 478a85cb24fSFrançois Tigeot 479a85cb24fSFrançois Tigeot /** 480a85cb24fSFrançois Tigeot * drm_read - read method for DRM file 481a85cb24fSFrançois Tigeot * @filp: file pointer 482a85cb24fSFrançois Tigeot * @buffer: userspace destination pointer for the read 483a85cb24fSFrançois Tigeot * @count: count in bytes to read 484a85cb24fSFrançois Tigeot * @offset: offset to read 485a85cb24fSFrançois Tigeot * 486*3f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.read 487a85cb24fSFrançois Tigeot * method iff they use DRM events for asynchronous signalling to userspace. 488a85cb24fSFrançois Tigeot * Since events are used by the KMS API for vblank and page flip completion this 489a85cb24fSFrançois Tigeot * means all modern display drivers must use it. 490a85cb24fSFrançois Tigeot * 491*3f2dd94aSFrançois Tigeot * @offset is ignored, DRM events are read like a pipe. Therefore drivers also 492*3f2dd94aSFrançois Tigeot * must set the &file_operation.llseek to no_llseek(). Polling support is 493a85cb24fSFrançois Tigeot * provided by drm_poll(). 494a85cb24fSFrançois Tigeot * 495a85cb24fSFrançois Tigeot * This function will only ever read a full event. Therefore userspace must 496a85cb24fSFrançois Tigeot * supply a big enough buffer to fit any event to ensure forward progress. Since 497a85cb24fSFrançois Tigeot * the maximum event space is currently 4K it's recommended to just use that for 498a85cb24fSFrançois Tigeot * safety. 499a85cb24fSFrançois Tigeot * 500a85cb24fSFrançois Tigeot * RETURNS: 501a85cb24fSFrançois Tigeot * 502a85cb24fSFrançois Tigeot * Number of bytes read (always aligned to full events, and can be 0) or a 503a85cb24fSFrançois Tigeot * negative error code on failure. 504a85cb24fSFrançois Tigeot */ 505a85cb24fSFrançois Tigeot /* 506a85cb24fSFrançois Tigeot ssize_t drm_read(struct file *filp, char __user *buffer, 507a85cb24fSFrançois Tigeot size_t count, loff_t *offset) 508a85cb24fSFrançois Tigeot */ 509a85cb24fSFrançois Tigeot int drm_read(struct dev_read_args *ap) 510a85cb24fSFrançois Tigeot { 511a85cb24fSFrançois Tigeot struct file *filp = ap->a_fp; 512a85cb24fSFrançois Tigeot struct uio *uio = ap->a_uio; 513a85cb24fSFrançois Tigeot size_t count = uio->uio_resid; 514a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 515*3f2dd94aSFrançois Tigeot struct drm_device *dev = file_priv->minor->dev; 516a85cb24fSFrançois Tigeot int ret = 0; /* drm_read() returns int in DragonFly */ 517a85cb24fSFrançois Tigeot 518a85cb24fSFrançois Tigeot ret = mutex_lock_interruptible(&file_priv->event_read_lock); 519a85cb24fSFrançois Tigeot if (ret) 520a85cb24fSFrançois Tigeot return ret; 521a85cb24fSFrançois Tigeot 522a85cb24fSFrançois Tigeot for (;;) { 523a85cb24fSFrançois Tigeot struct drm_pending_event *e = NULL; 524a85cb24fSFrançois Tigeot 525a85cb24fSFrançois Tigeot spin_lock_irq(&dev->event_lock); 526a85cb24fSFrançois Tigeot if (!list_empty(&file_priv->event_list)) { 527a85cb24fSFrançois Tigeot e = list_first_entry(&file_priv->event_list, 528a85cb24fSFrançois Tigeot struct drm_pending_event, link); 529a85cb24fSFrançois Tigeot file_priv->event_space += e->event->length; 530a85cb24fSFrançois Tigeot list_del(&e->link); 531a85cb24fSFrançois Tigeot } 532a85cb24fSFrançois Tigeot spin_unlock_irq(&dev->event_lock); 533a85cb24fSFrançois Tigeot 534a85cb24fSFrançois Tigeot if (e == NULL) { 535a85cb24fSFrançois Tigeot if (ret) { 536a85cb24fSFrançois Tigeot ret = 0; /* DragonFly expects a zero return value on success */ 537a85cb24fSFrançois Tigeot break; 538a85cb24fSFrançois Tigeot } 539a85cb24fSFrançois Tigeot 540a85cb24fSFrançois Tigeot if (filp->f_flag & O_NONBLOCK) { 541a85cb24fSFrançois Tigeot ret = -EAGAIN; 542a85cb24fSFrançois Tigeot break; 543a85cb24fSFrançois Tigeot } 544a85cb24fSFrançois Tigeot 545a85cb24fSFrançois Tigeot mutex_unlock(&file_priv->event_read_lock); 546a85cb24fSFrançois Tigeot ret = wait_event_interruptible(file_priv->event_wait, 547a85cb24fSFrançois Tigeot !list_empty(&file_priv->event_list)); 548a85cb24fSFrançois Tigeot if (ret >= 0) 549a85cb24fSFrançois Tigeot ret = mutex_lock_interruptible(&file_priv->event_read_lock); 550a85cb24fSFrançois Tigeot if (ret) 551a85cb24fSFrançois Tigeot return ret; 552a85cb24fSFrançois Tigeot } else { 553a85cb24fSFrançois Tigeot unsigned length = e->event->length; 554a85cb24fSFrançois Tigeot 555a85cb24fSFrançois Tigeot if (length > count - ret) { 556a85cb24fSFrançois Tigeot put_back_event: 557a85cb24fSFrançois Tigeot spin_lock_irq(&dev->event_lock); 558a85cb24fSFrançois Tigeot file_priv->event_space -= length; 559a85cb24fSFrançois Tigeot list_add(&e->link, &file_priv->event_list); 560a85cb24fSFrançois Tigeot spin_unlock_irq(&dev->event_lock); 561a85cb24fSFrançois Tigeot break; 562a85cb24fSFrançois Tigeot } 563a85cb24fSFrançois Tigeot 564a85cb24fSFrançois Tigeot if (uiomove((caddr_t)e->event, length, uio)) { 565a85cb24fSFrançois Tigeot if (ret == 0) 566a85cb24fSFrançois Tigeot ret = -EFAULT; 567a85cb24fSFrançois Tigeot goto put_back_event; 568a85cb24fSFrançois Tigeot } 569a85cb24fSFrançois Tigeot 570a85cb24fSFrançois Tigeot ret += length; 571a85cb24fSFrançois Tigeot kfree(e); 572a85cb24fSFrançois Tigeot } 573a85cb24fSFrançois Tigeot } 574a85cb24fSFrançois Tigeot mutex_unlock(&file_priv->event_read_lock); 575a85cb24fSFrançois Tigeot 576a85cb24fSFrançois Tigeot return ret; 577a85cb24fSFrançois Tigeot } 578a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_read); 579a85cb24fSFrançois Tigeot 580a85cb24fSFrançois Tigeot /** 581a85cb24fSFrançois Tigeot * drm_poll - poll method for DRM file 582a85cb24fSFrançois Tigeot * @filp: file pointer 583a85cb24fSFrançois Tigeot * @wait: poll waiter table 584a85cb24fSFrançois Tigeot * 585*3f2dd94aSFrançois Tigeot * This function must be used by drivers as their &file_operations.read method 586*3f2dd94aSFrançois Tigeot * iff they use DRM events for asynchronous signalling to userspace. Since 587*3f2dd94aSFrançois Tigeot * events are used by the KMS API for vblank and page flip completion this means 588*3f2dd94aSFrançois Tigeot * all modern display drivers must use it. 589a85cb24fSFrançois Tigeot * 590a85cb24fSFrançois Tigeot * See also drm_read(). 591a85cb24fSFrançois Tigeot * 592a85cb24fSFrançois Tigeot * RETURNS: 593a85cb24fSFrançois Tigeot * 594a85cb24fSFrançois Tigeot * Mask of POLL flags indicating the current status of the file. 595a85cb24fSFrançois Tigeot */ 596a85cb24fSFrançois Tigeot static int 597a85cb24fSFrançois Tigeot drmfilt(struct knote *kn, long hint) 598a85cb24fSFrançois Tigeot { 599a85cb24fSFrançois Tigeot struct drm_file *file_priv = (struct drm_file *)kn->kn_hook; 600a85cb24fSFrançois Tigeot int ready = 0; 601a85cb24fSFrançois Tigeot 602a85cb24fSFrançois Tigeot // poll_wait(filp, &file_priv->event_wait, wait); 603a85cb24fSFrançois Tigeot 604a85cb24fSFrançois Tigeot if (!list_empty(&file_priv->event_list)) 605a85cb24fSFrançois Tigeot ready = 1; 606a85cb24fSFrançois Tigeot 607a85cb24fSFrançois Tigeot return (ready); 608a85cb24fSFrançois Tigeot } 609a85cb24fSFrançois Tigeot 610a85cb24fSFrançois Tigeot static void 611a85cb24fSFrançois Tigeot drmfilt_detach(struct knote *kn) 612a85cb24fSFrançois Tigeot { 613a85cb24fSFrançois Tigeot struct drm_file *file_priv; 614a85cb24fSFrançois Tigeot struct klist *klist; 615a85cb24fSFrançois Tigeot 616a85cb24fSFrançois Tigeot file_priv = (struct drm_file *)kn->kn_hook; 617a85cb24fSFrançois Tigeot 618a85cb24fSFrançois Tigeot klist = &file_priv->dkq.ki_note; 619a85cb24fSFrançois Tigeot knote_remove(klist, kn); 620a85cb24fSFrançois Tigeot } 621a85cb24fSFrançois Tigeot 622a85cb24fSFrançois Tigeot static struct filterops drmfiltops = 623a85cb24fSFrançois Tigeot { FILTEROP_MPSAFE | FILTEROP_ISFD, NULL, drmfilt_detach, drmfilt }; 624a85cb24fSFrançois Tigeot 625a85cb24fSFrançois Tigeot int 626a85cb24fSFrançois Tigeot drm_kqfilter(struct dev_kqfilter_args *ap) 627a85cb24fSFrançois Tigeot { 628a85cb24fSFrançois Tigeot struct file *filp = ap->a_fp; 629a85cb24fSFrançois Tigeot struct drm_file *file_priv = filp->private_data; 630a85cb24fSFrançois Tigeot struct knote *kn = ap->a_kn; 631a85cb24fSFrançois Tigeot struct klist *klist; 632a85cb24fSFrançois Tigeot 633a85cb24fSFrançois Tigeot ap->a_result = 0; 634a85cb24fSFrançois Tigeot 635a85cb24fSFrançois Tigeot switch (kn->kn_filter) { 636a85cb24fSFrançois Tigeot case EVFILT_READ: 637a85cb24fSFrançois Tigeot case EVFILT_WRITE: 638a85cb24fSFrançois Tigeot kn->kn_fop = &drmfiltops; 639a85cb24fSFrançois Tigeot kn->kn_hook = (caddr_t)file_priv; 640a85cb24fSFrançois Tigeot break; 641a85cb24fSFrançois Tigeot default: 642a85cb24fSFrançois Tigeot ap->a_result = EOPNOTSUPP; 643a85cb24fSFrançois Tigeot return (0); 644a85cb24fSFrançois Tigeot } 645a85cb24fSFrançois Tigeot 646a85cb24fSFrançois Tigeot klist = &file_priv->dkq.ki_note; 647a85cb24fSFrançois Tigeot knote_insert(klist, kn); 648a85cb24fSFrançois Tigeot 649a85cb24fSFrançois Tigeot return (0); 650a85cb24fSFrançois Tigeot } 651a85cb24fSFrançois Tigeot 652a85cb24fSFrançois Tigeot /** 653a85cb24fSFrançois Tigeot * drm_event_reserve_init_locked - init a DRM event and reserve space for it 654a85cb24fSFrançois Tigeot * @dev: DRM device 655a85cb24fSFrançois Tigeot * @file_priv: DRM file private data 656a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 657a85cb24fSFrançois Tigeot * @e: actual event data to deliver to userspace 658a85cb24fSFrançois Tigeot * 659a85cb24fSFrançois Tigeot * This function prepares the passed in event for eventual delivery. If the event 660a85cb24fSFrançois Tigeot * doesn't get delivered (because the IOCTL fails later on, before queuing up 661a85cb24fSFrançois Tigeot * anything) then the even must be cancelled and freed using 662a85cb24fSFrançois Tigeot * drm_event_cancel_free(). Successfully initialized events should be sent out 663a85cb24fSFrançois Tigeot * using drm_send_event() or drm_send_event_locked() to signal completion of the 664a85cb24fSFrançois Tigeot * asynchronous event to userspace. 665a85cb24fSFrançois Tigeot * 666a85cb24fSFrançois Tigeot * If callers embedded @p into a larger structure it must be allocated with 667a85cb24fSFrançois Tigeot * kmalloc and @p must be the first member element. 668a85cb24fSFrançois Tigeot * 669a85cb24fSFrançois Tigeot * This is the locked version of drm_event_reserve_init() for callers which 670a85cb24fSFrançois Tigeot * already hold &drm_device.event_lock. 671a85cb24fSFrançois Tigeot * 672a85cb24fSFrançois Tigeot * RETURNS: 673a85cb24fSFrançois Tigeot * 674a85cb24fSFrançois Tigeot * 0 on success or a negative error code on failure. 675a85cb24fSFrançois Tigeot */ 676a85cb24fSFrançois Tigeot int drm_event_reserve_init_locked(struct drm_device *dev, 677a85cb24fSFrançois Tigeot struct drm_file *file_priv, 678a85cb24fSFrançois Tigeot struct drm_pending_event *p, 679a85cb24fSFrançois Tigeot struct drm_event *e) 680a85cb24fSFrançois Tigeot { 681a85cb24fSFrançois Tigeot if (file_priv->event_space < e->length) 682a85cb24fSFrançois Tigeot return -ENOMEM; 683a85cb24fSFrançois Tigeot 684a85cb24fSFrançois Tigeot file_priv->event_space -= e->length; 685a85cb24fSFrançois Tigeot 686a85cb24fSFrançois Tigeot p->event = e; 687a85cb24fSFrançois Tigeot list_add(&p->pending_link, &file_priv->pending_event_list); 688a85cb24fSFrançois Tigeot p->file_priv = file_priv; 689a85cb24fSFrançois Tigeot 690a85cb24fSFrançois Tigeot return 0; 691a85cb24fSFrançois Tigeot } 692a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_reserve_init_locked); 693a85cb24fSFrançois Tigeot 694a85cb24fSFrançois Tigeot /** 695a85cb24fSFrançois Tigeot * drm_event_reserve_init - init a DRM event and reserve space for it 696a85cb24fSFrançois Tigeot * @dev: DRM device 697a85cb24fSFrançois Tigeot * @file_priv: DRM file private data 698a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 699a85cb24fSFrançois Tigeot * @e: actual event data to deliver to userspace 700a85cb24fSFrançois Tigeot * 701a85cb24fSFrançois Tigeot * This function prepares the passed in event for eventual delivery. If the event 702a85cb24fSFrançois Tigeot * doesn't get delivered (because the IOCTL fails later on, before queuing up 703a85cb24fSFrançois Tigeot * anything) then the even must be cancelled and freed using 704a85cb24fSFrançois Tigeot * drm_event_cancel_free(). Successfully initialized events should be sent out 705a85cb24fSFrançois Tigeot * using drm_send_event() or drm_send_event_locked() to signal completion of the 706a85cb24fSFrançois Tigeot * asynchronous event to userspace. 707a85cb24fSFrançois Tigeot * 708a85cb24fSFrançois Tigeot * If callers embedded @p into a larger structure it must be allocated with 709a85cb24fSFrançois Tigeot * kmalloc and @p must be the first member element. 710a85cb24fSFrançois Tigeot * 711a85cb24fSFrançois Tigeot * Callers which already hold &drm_device.event_lock should use 712a85cb24fSFrançois Tigeot * drm_event_reserve_init_locked() instead. 713a85cb24fSFrançois Tigeot * 714a85cb24fSFrançois Tigeot * RETURNS: 715a85cb24fSFrançois Tigeot * 716a85cb24fSFrançois Tigeot * 0 on success or a negative error code on failure. 717a85cb24fSFrançois Tigeot */ 718a85cb24fSFrançois Tigeot int drm_event_reserve_init(struct drm_device *dev, 719a85cb24fSFrançois Tigeot struct drm_file *file_priv, 720a85cb24fSFrançois Tigeot struct drm_pending_event *p, 721a85cb24fSFrançois Tigeot struct drm_event *e) 722a85cb24fSFrançois Tigeot { 723a85cb24fSFrançois Tigeot unsigned long flags; 724a85cb24fSFrançois Tigeot int ret; 725a85cb24fSFrançois Tigeot 726a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 727a85cb24fSFrançois Tigeot ret = drm_event_reserve_init_locked(dev, file_priv, p, e); 728a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 729a85cb24fSFrançois Tigeot 730a85cb24fSFrançois Tigeot return ret; 731a85cb24fSFrançois Tigeot } 732a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_reserve_init); 733a85cb24fSFrançois Tigeot 734a85cb24fSFrançois Tigeot /** 735a85cb24fSFrançois Tigeot * drm_event_cancel_free - free a DRM event and release it's space 736a85cb24fSFrançois Tigeot * @dev: DRM device 737a85cb24fSFrançois Tigeot * @p: tracking structure for the pending event 738a85cb24fSFrançois Tigeot * 739a85cb24fSFrançois Tigeot * This function frees the event @p initialized with drm_event_reserve_init() 740*3f2dd94aSFrançois Tigeot * and releases any allocated space. It is used to cancel an event when the 741*3f2dd94aSFrançois Tigeot * nonblocking operation could not be submitted and needed to be aborted. 742a85cb24fSFrançois Tigeot */ 743a85cb24fSFrançois Tigeot void drm_event_cancel_free(struct drm_device *dev, 744a85cb24fSFrançois Tigeot struct drm_pending_event *p) 745a85cb24fSFrançois Tigeot { 746a85cb24fSFrançois Tigeot unsigned long flags; 747a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, flags); 748a85cb24fSFrançois Tigeot if (p->file_priv) { 749a85cb24fSFrançois Tigeot p->file_priv->event_space += p->event->length; 750a85cb24fSFrançois Tigeot list_del(&p->pending_link); 751a85cb24fSFrançois Tigeot } 752a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, flags); 753*3f2dd94aSFrançois Tigeot 754*3f2dd94aSFrançois Tigeot if (p->fence) 755*3f2dd94aSFrançois Tigeot dma_fence_put(p->fence); 756*3f2dd94aSFrançois Tigeot 757a85cb24fSFrançois Tigeot kfree(p); 758a85cb24fSFrançois Tigeot } 759a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_event_cancel_free); 760a85cb24fSFrançois Tigeot 761a85cb24fSFrançois Tigeot /** 762a85cb24fSFrançois Tigeot * drm_send_event_locked - send DRM event to file descriptor 763a85cb24fSFrançois Tigeot * @dev: DRM device 764a85cb24fSFrançois Tigeot * @e: DRM event to deliver 765a85cb24fSFrançois Tigeot * 766a85cb24fSFrançois Tigeot * This function sends the event @e, initialized with drm_event_reserve_init(), 767a85cb24fSFrançois Tigeot * to its associated userspace DRM file. Callers must already hold 768a85cb24fSFrançois Tigeot * &drm_device.event_lock, see drm_send_event() for the unlocked version. 769a85cb24fSFrançois Tigeot * 770a85cb24fSFrançois Tigeot * Note that the core will take care of unlinking and disarming events when the 771a85cb24fSFrançois Tigeot * corresponding DRM file is closed. Drivers need not worry about whether the 772a85cb24fSFrançois Tigeot * DRM file for this event still exists and can call this function upon 773a85cb24fSFrançois Tigeot * completion of the asynchronous work unconditionally. 774a85cb24fSFrançois Tigeot */ 775a85cb24fSFrançois Tigeot void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) 776a85cb24fSFrançois Tigeot { 777a85cb24fSFrançois Tigeot assert_spin_locked(&dev->event_lock); 778a85cb24fSFrançois Tigeot 779a85cb24fSFrançois Tigeot if (e->completion) { 780a85cb24fSFrançois Tigeot complete_all(e->completion); 781a85cb24fSFrançois Tigeot e->completion_release(e->completion); 782a85cb24fSFrançois Tigeot e->completion = NULL; 783a85cb24fSFrançois Tigeot } 784a85cb24fSFrançois Tigeot 785a85cb24fSFrançois Tigeot if (e->fence) { 786a85cb24fSFrançois Tigeot dma_fence_signal(e->fence); 787a85cb24fSFrançois Tigeot dma_fence_put(e->fence); 788a85cb24fSFrançois Tigeot } 789a85cb24fSFrançois Tigeot 790a85cb24fSFrançois Tigeot if (!e->file_priv) { 791a85cb24fSFrançois Tigeot kfree(e); 792a85cb24fSFrançois Tigeot return; 793a85cb24fSFrançois Tigeot } 794a85cb24fSFrançois Tigeot 795a85cb24fSFrançois Tigeot list_del(&e->pending_link); 796a85cb24fSFrançois Tigeot list_add_tail(&e->link, 797a85cb24fSFrançois Tigeot &e->file_priv->event_list); 798a85cb24fSFrançois Tigeot wake_up_interruptible(&e->file_priv->event_wait); 799a85cb24fSFrançois Tigeot #ifdef __DragonFly__ 800a85cb24fSFrançois Tigeot KNOTE(&e->file_priv->dkq.ki_note, 0); 801a85cb24fSFrançois Tigeot #endif 802a85cb24fSFrançois Tigeot } 803a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_send_event_locked); 804a85cb24fSFrançois Tigeot 805a85cb24fSFrançois Tigeot /** 806a85cb24fSFrançois Tigeot * drm_send_event - send DRM event to file descriptor 807a85cb24fSFrançois Tigeot * @dev: DRM device 808a85cb24fSFrançois Tigeot * @e: DRM event to deliver 809a85cb24fSFrançois Tigeot * 810a85cb24fSFrançois Tigeot * This function sends the event @e, initialized with drm_event_reserve_init(), 811a85cb24fSFrançois Tigeot * to its associated userspace DRM file. This function acquires 812a85cb24fSFrançois Tigeot * &drm_device.event_lock, see drm_send_event_locked() for callers which already 813a85cb24fSFrançois Tigeot * hold this lock. 814a85cb24fSFrançois Tigeot * 815a85cb24fSFrançois Tigeot * Note that the core will take care of unlinking and disarming events when the 816a85cb24fSFrançois Tigeot * corresponding DRM file is closed. Drivers need not worry about whether the 817a85cb24fSFrançois Tigeot * DRM file for this event still exists and can call this function upon 818a85cb24fSFrançois Tigeot * completion of the asynchronous work unconditionally. 819a85cb24fSFrançois Tigeot */ 820a85cb24fSFrançois Tigeot void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) 821a85cb24fSFrançois Tigeot { 822a85cb24fSFrançois Tigeot unsigned long irqflags; 823a85cb24fSFrançois Tigeot 824a85cb24fSFrançois Tigeot spin_lock_irqsave(&dev->event_lock, irqflags); 825a85cb24fSFrançois Tigeot drm_send_event_locked(dev, e); 826a85cb24fSFrançois Tigeot spin_unlock_irqrestore(&dev->event_lock, irqflags); 827a85cb24fSFrançois Tigeot } 828a85cb24fSFrançois Tigeot EXPORT_SYMBOL(drm_send_event); 829