linux/drivers/gpu/drm/drm_fops.c
<<
>>
Prefs
   1/**
   2 * \file drm_fops.c
   3 * File operations for DRM
   4 *
   5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
   6 * \author Daryll Strauss <daryll@valinux.com>
   7 * \author Gareth Hughes <gareth@valinux.com>
   8 */
   9
  10/*
  11 * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
  12 *
  13 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  14 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  15 * All Rights Reserved.
  16 *
  17 * Permission is hereby granted, free of charge, to any person obtaining a
  18 * copy of this software and associated documentation files (the "Software"),
  19 * to deal in the Software without restriction, including without limitation
  20 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  21 * and/or sell copies of the Software, and to permit persons to whom the
  22 * Software is furnished to do so, subject to the following conditions:
  23 *
  24 * The above copyright notice and this permission notice (including the next
  25 * paragraph) shall be included in all copies or substantial portions of the
  26 * Software.
  27 *
  28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  31 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  32 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  33 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  34 * OTHER DEALINGS IN THE SOFTWARE.
  35 */
  36
  37#include <drm/drmP.h>
  38#include <linux/poll.h>
  39#include <linux/slab.h>
  40#include <linux/module.h>
  41#include "drm_legacy.h"
  42#include "drm_internal.h"
  43
  44/* from BKL pushdown */
  45DEFINE_MUTEX(drm_global_mutex);
  46
  47static int drm_open_helper(struct file *filp, struct drm_minor *minor);
  48
  49static int drm_setup(struct drm_device * dev)
  50{
  51        int ret;
  52
  53        if (dev->driver->firstopen &&
  54            !drm_core_check_feature(dev, DRIVER_MODESET)) {
  55                ret = dev->driver->firstopen(dev);
  56                if (ret != 0)
  57                        return ret;
  58        }
  59
  60        ret = drm_legacy_dma_setup(dev);
  61        if (ret < 0)
  62                return ret;
  63
  64
  65        DRM_DEBUG("\n");
  66        return 0;
  67}
  68
  69/**
  70 * Open file.
  71 *
  72 * \param inode device inode
  73 * \param filp file pointer.
  74 * \return zero on success or a negative number on failure.
  75 *
  76 * Searches the DRM device with the same minor number, calls open_helper(), and
  77 * increments the device open count. If the open count was previous at zero,
  78 * i.e., it's the first that the device is open, then calls setup().
  79 */
  80int drm_open(struct inode *inode, struct file *filp)
  81{
  82        struct drm_device *dev;
  83        struct drm_minor *minor;
  84        int retcode;
  85        int need_setup = 0;
  86
  87        minor = drm_minor_acquire(iminor(inode));
  88        if (IS_ERR(minor))
  89                return PTR_ERR(minor);
  90
  91        dev = minor->dev;
  92        if (!dev->open_count++)
  93                need_setup = 1;
  94
  95        /* share address_space across all char-devs of a single device */
  96        filp->f_mapping = dev->anon_inode->i_mapping;
  97
  98        retcode = drm_open_helper(filp, minor);
  99        if (retcode)
 100                goto err_undo;
 101        if (need_setup) {
 102                retcode = drm_setup(dev);
 103                if (retcode)
 104                        goto err_undo;
 105        }
 106        return 0;
 107
 108err_undo:
 109        dev->open_count--;
 110        drm_minor_release(minor);
 111        return retcode;
 112}
 113EXPORT_SYMBOL(drm_open);
 114
 115/**
 116 * Check whether DRI will run on this CPU.
 117 *
 118 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
 119 */
 120static int drm_cpu_valid(void)
 121{
 122#if defined(__sparc__) && !defined(__sparc_v9__)
 123        return 0;               /* No cmpxchg before v9 sparc. */
 124#endif
 125        return 1;
 126}
 127
 128/**
 129 * Called whenever a process opens /dev/drm.
 130 *
 131 * \param filp file pointer.
 132 * \param minor acquired minor-object.
 133 * \return zero on success or a negative number on failure.
 134 *
 135 * Creates and initializes a drm_file structure for the file private data in \p
 136 * filp and add it into the double linked list in \p dev.
 137 */
 138static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 139{
 140        struct drm_device *dev = minor->dev;
 141        struct drm_file *priv;
 142        int ret;
 143
 144        if (filp->f_flags & O_EXCL)
 145                return -EBUSY;  /* No exclusive opens */
 146        if (!drm_cpu_valid())
 147                return -EINVAL;
 148        if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
 149                return -EINVAL;
 150
 151        DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
 152
 153        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 154        if (!priv)
 155                return -ENOMEM;
 156
 157        filp->private_data = priv;
 158        priv->filp = filp;
 159        priv->uid = current_euid();
 160        priv->pid = get_pid(task_pid(current));
 161        priv->minor = minor;
 162
 163        /* for compatibility root is always authenticated */
 164        priv->authenticated = capable(CAP_SYS_ADMIN);
 165        priv->lock_count = 0;
 166
 167        INIT_LIST_HEAD(&priv->lhead);
 168        INIT_LIST_HEAD(&priv->fbs);
 169        mutex_init(&priv->fbs_lock);
 170        INIT_LIST_HEAD(&priv->blobs);
 171        INIT_LIST_HEAD(&priv->event_list);
 172        init_waitqueue_head(&priv->event_wait);
 173        priv->event_space = 4096; /* set aside 4k for event buffer */
 174
 175        if (drm_core_check_feature(dev, DRIVER_GEM))
 176                drm_gem_open(dev, priv);
 177
 178        if (drm_core_check_feature(dev, DRIVER_PRIME))
 179                drm_prime_init_file_private(&priv->prime);
 180
 181        if (dev->driver->open) {
 182                ret = dev->driver->open(dev, priv);
 183                if (ret < 0)
 184                        goto out_prime_destroy;
 185        }
 186
 187        /* if there is no current master make this fd it, but do not create
 188         * any master object for render clients */
 189        mutex_lock(&dev->master_mutex);
 190        if (drm_is_primary_client(priv) && !priv->minor->master) {
 191                /* create a new master */
 192                priv->minor->master = drm_master_create(priv->minor);
 193                if (!priv->minor->master) {
 194                        ret = -ENOMEM;
 195                        goto out_close;
 196                }
 197
 198                priv->is_master = 1;
 199                /* take another reference for the copy in the local file priv */
 200                priv->master = drm_master_get(priv->minor->master);
 201                priv->authenticated = 1;
 202
 203                if (dev->driver->master_create) {
 204                        ret = dev->driver->master_create(dev, priv->master);
 205                        if (ret) {
 206                                /* drop both references if this fails */
 207                                drm_master_put(&priv->minor->master);
 208                                drm_master_put(&priv->master);
 209                                goto out_close;
 210                        }
 211                }
 212                if (dev->driver->master_set) {
 213                        ret = dev->driver->master_set(dev, priv, true);
 214                        if (ret) {
 215                                /* drop both references if this fails */
 216                                drm_master_put(&priv->minor->master);
 217                                drm_master_put(&priv->master);
 218                                goto out_close;
 219                        }
 220                }
 221        } else if (drm_is_primary_client(priv)) {
 222                /* get a reference to the master */
 223                priv->master = drm_master_get(priv->minor->master);
 224        }
 225        mutex_unlock(&dev->master_mutex);
 226
 227        mutex_lock(&dev->struct_mutex);
 228        list_add(&priv->lhead, &dev->filelist);
 229        mutex_unlock(&dev->struct_mutex);
 230
 231#ifdef __alpha__
 232        /*
 233         * Default the hose
 234         */
 235        if (!dev->hose) {
 236                struct pci_dev *pci_dev;
 237                pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
 238                if (pci_dev) {
 239                        dev->hose = pci_dev->sysdata;
 240                        pci_dev_put(pci_dev);
 241                }
 242                if (!dev->hose) {
 243                        struct pci_bus *b = list_entry(pci_root_buses.next,
 244                                struct pci_bus, node);
 245                        if (b)
 246                                dev->hose = b->sysdata;
 247                }
 248        }
 249#endif
 250
 251        return 0;
 252
 253out_close:
 254        mutex_unlock(&dev->master_mutex);
 255        if (dev->driver->postclose)
 256                dev->driver->postclose(dev, priv);
 257out_prime_destroy:
 258        if (drm_core_check_feature(dev, DRIVER_PRIME))
 259                drm_prime_destroy_file_private(&priv->prime);
 260        if (drm_core_check_feature(dev, DRIVER_GEM))
 261                drm_gem_release(dev, priv);
 262        put_pid(priv->pid);
 263        kfree(priv);
 264        filp->private_data = NULL;
 265        return ret;
 266}
 267
 268static void drm_master_release(struct drm_device *dev, struct file *filp)
 269{
 270        struct drm_file *file_priv = filp->private_data;
 271
 272        if (drm_legacy_i_have_hw_lock(dev, file_priv)) {
 273                DRM_DEBUG("File %p released, freeing lock for context %d\n",
 274                          filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
 275                drm_legacy_lock_free(&file_priv->master->lock,
 276                                     _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
 277        }
 278}
 279
 280static void drm_events_release(struct drm_file *file_priv)
 281{
 282        struct drm_device *dev = file_priv->minor->dev;
 283        struct drm_pending_event *e, *et;
 284        struct drm_pending_vblank_event *v, *vt;
 285        unsigned long flags;
 286
 287        spin_lock_irqsave(&dev->event_lock, flags);
 288
 289        /* Remove pending flips */
 290        list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
 291                if (v->base.file_priv == file_priv) {
 292                        list_del(&v->base.link);
 293                        drm_vblank_put(dev, v->pipe);
 294                        v->base.destroy(&v->base);
 295                }
 296
 297        /* Remove unconsumed events */
 298        list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
 299                list_del(&e->link);
 300                e->destroy(e);
 301        }
 302
 303        spin_unlock_irqrestore(&dev->event_lock, flags);
 304}
 305
 306/**
 307 * drm_legacy_dev_reinit
 308 *
 309 * Reinitializes a legacy/ums drm device in it's lastclose function.
 310 */
 311static void drm_legacy_dev_reinit(struct drm_device *dev)
 312{
 313        if (drm_core_check_feature(dev, DRIVER_MODESET))
 314                return;
 315
 316        dev->sigdata.lock = NULL;
 317
 318        dev->context_flag = 0;
 319        dev->last_context = 0;
 320        dev->if_version = 0;
 321}
 322
 323/**
 324 * Take down the DRM device.
 325 *
 326 * \param dev DRM device structure.
 327 *
 328 * Frees every resource in \p dev.
 329 *
 330 * \sa drm_device
 331 */
 332int drm_lastclose(struct drm_device * dev)
 333{
 334        DRM_DEBUG("\n");
 335
 336        if (dev->driver->lastclose)
 337                dev->driver->lastclose(dev);
 338        DRM_DEBUG("driver lastclose completed\n");
 339
 340        if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
 341                drm_irq_uninstall(dev);
 342
 343        mutex_lock(&dev->struct_mutex);
 344
 345        drm_agp_clear(dev);
 346
 347        drm_legacy_sg_cleanup(dev);
 348        drm_legacy_vma_flush(dev);
 349        drm_legacy_dma_takedown(dev);
 350
 351        mutex_unlock(&dev->struct_mutex);
 352
 353        drm_legacy_dev_reinit(dev);
 354
 355        DRM_DEBUG("lastclose completed\n");
 356        return 0;
 357}
 358
 359/**
 360 * Release file.
 361 *
 362 * \param inode device inode
 363 * \param file_priv DRM file private.
 364 * \return zero on success or a negative number on failure.
 365 *
 366 * If the hardware lock is held then free it, and take it again for the kernel
 367 * context since it's necessary to reclaim buffers. Unlink the file private
 368 * data from its list and free it. Decreases the open count and if it reaches
 369 * zero calls drm_lastclose().
 370 */
 371int drm_release(struct inode *inode, struct file *filp)
 372{
 373        struct drm_file *file_priv = filp->private_data;
 374        struct drm_minor *minor = file_priv->minor;
 375        struct drm_device *dev = minor->dev;
 376        int retcode = 0;
 377
 378        mutex_lock(&drm_global_mutex);
 379
 380        DRM_DEBUG("open_count = %d\n", dev->open_count);
 381
 382        mutex_lock(&dev->struct_mutex);
 383        list_del(&file_priv->lhead);
 384        if (file_priv->magic)
 385                idr_remove(&file_priv->master->magic_map, file_priv->magic);
 386        mutex_unlock(&dev->struct_mutex);
 387
 388        if (dev->driver->preclose)
 389                dev->driver->preclose(dev, file_priv);
 390
 391        /* ========================================================
 392         * Begin inline drm_release
 393         */
 394
 395        DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
 396                  task_pid_nr(current),
 397                  (long)old_encode_dev(file_priv->minor->kdev->devt),
 398                  dev->open_count);
 399
 400        /* if the master has gone away we can't do anything with the lock */
 401        if (file_priv->minor->master)
 402                drm_master_release(dev, filp);
 403
 404        if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 405                drm_legacy_reclaim_buffers(dev, file_priv);
 406
 407        drm_events_release(file_priv);
 408
 409        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 410                drm_fb_release(file_priv);
 411                drm_property_destroy_user_blobs(dev, file_priv);
 412        }
 413
 414        if (drm_core_check_feature(dev, DRIVER_GEM))
 415                drm_gem_release(dev, file_priv);
 416
 417        drm_legacy_ctxbitmap_flush(dev, file_priv);
 418
 419        mutex_lock(&dev->master_mutex);
 420
 421        if (file_priv->is_master) {
 422                struct drm_master *master = file_priv->master;
 423
 424                /**
 425                 * Since the master is disappearing, so is the
 426                 * possibility to lock.
 427                 */
 428                mutex_lock(&dev->struct_mutex);
 429                if (master->lock.hw_lock) {
 430                        if (dev->sigdata.lock == master->lock.hw_lock)
 431                                dev->sigdata.lock = NULL;
 432                        master->lock.hw_lock = NULL;
 433                        master->lock.file_priv = NULL;
 434                        wake_up_interruptible_all(&master->lock.lock_queue);
 435                }
 436                mutex_unlock(&dev->struct_mutex);
 437
 438                if (file_priv->minor->master == file_priv->master) {
 439                        /* drop the reference held my the minor */
 440                        if (dev->driver->master_drop)
 441                                dev->driver->master_drop(dev, file_priv, true);
 442                        drm_master_put(&file_priv->minor->master);
 443                }
 444        }
 445
 446        /* drop the master reference held by the file priv */
 447        if (file_priv->master)
 448                drm_master_put(&file_priv->master);
 449        file_priv->is_master = 0;
 450        mutex_unlock(&dev->master_mutex);
 451
 452        if (dev->driver->postclose)
 453                dev->driver->postclose(dev, file_priv);
 454
 455
 456        if (drm_core_check_feature(dev, DRIVER_PRIME))
 457                drm_prime_destroy_file_private(&file_priv->prime);
 458
 459        WARN_ON(!list_empty(&file_priv->event_list));
 460
 461        put_pid(file_priv->pid);
 462        kfree(file_priv);
 463
 464        /* ========================================================
 465         * End inline drm_release
 466         */
 467
 468        if (!--dev->open_count) {
 469                retcode = drm_lastclose(dev);
 470                if (drm_device_is_unplugged(dev))
 471                        drm_put_dev(dev);
 472        }
 473        mutex_unlock(&drm_global_mutex);
 474
 475        drm_minor_release(minor);
 476
 477        return retcode;
 478}
 479EXPORT_SYMBOL(drm_release);
 480
 481ssize_t drm_read(struct file *filp, char __user *buffer,
 482                 size_t count, loff_t *offset)
 483{
 484        struct drm_file *file_priv = filp->private_data;
 485        struct drm_device *dev = file_priv->minor->dev;
 486        ssize_t ret = 0;
 487
 488        if (!access_ok(VERIFY_WRITE, buffer, count))
 489                return -EFAULT;
 490
 491        spin_lock_irq(&dev->event_lock);
 492        for (;;) {
 493                if (list_empty(&file_priv->event_list)) {
 494                        if (ret)
 495                                break;
 496
 497                        if (filp->f_flags & O_NONBLOCK) {
 498                                ret = -EAGAIN;
 499                                break;
 500                        }
 501
 502                        spin_unlock_irq(&dev->event_lock);
 503                        ret = wait_event_interruptible(file_priv->event_wait,
 504                                                       !list_empty(&file_priv->event_list));
 505                        spin_lock_irq(&dev->event_lock);
 506                        if (ret < 0)
 507                                break;
 508
 509                        ret = 0;
 510                } else {
 511                        struct drm_pending_event *e;
 512
 513                        e = list_first_entry(&file_priv->event_list,
 514                                             struct drm_pending_event, link);
 515                        if (e->event->length + ret > count)
 516                                break;
 517
 518                        if (__copy_to_user_inatomic(buffer + ret,
 519                                                    e->event, e->event->length)) {
 520                                if (ret == 0)
 521                                        ret = -EFAULT;
 522                                break;
 523                        }
 524
 525                        file_priv->event_space += e->event->length;
 526                        ret += e->event->length;
 527                        list_del(&e->link);
 528                        e->destroy(e);
 529                }
 530        }
 531        spin_unlock_irq(&dev->event_lock);
 532
 533        return ret;
 534}
 535EXPORT_SYMBOL(drm_read);
 536
 537unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
 538{
 539        struct drm_file *file_priv = filp->private_data;
 540        unsigned int mask = 0;
 541
 542        poll_wait(filp, &file_priv->event_wait, wait);
 543
 544        if (!list_empty(&file_priv->event_list))
 545                mask |= POLLIN | POLLRDNORM;
 546
 547        return mask;
 548}
 549EXPORT_SYMBOL(drm_poll);
 550