linux/drivers/gpu/drm/drm_irq.c
<<
>>
Prefs
   1/**
   2 * \file drm_irq.c
   3 * IRQ support
   4 *
   5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
   6 * \author Gareth Hughes <gareth@valinux.com>
   7 */
   8
   9/*
  10 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
  11 *
  12 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  14 * All Rights Reserved.
  15 *
  16 * Permission is hereby granted, free of charge, to any person obtaining a
  17 * copy of this software and associated documentation files (the "Software"),
  18 * to deal in the Software without restriction, including without limitation
  19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  20 * and/or sell copies of the Software, and to permit persons to whom the
  21 * Software is furnished to do so, subject to the following conditions:
  22 *
  23 * The above copyright notice and this permission notice (including the next
  24 * paragraph) shall be included in all copies or substantial portions of the
  25 * Software.
  26 *
  27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  33 * OTHER DEALINGS IN THE SOFTWARE.
  34 */
  35
  36#include "drmP.h"
  37
  38#include <linux/interrupt.h>    /* For task queue support */
  39
  40#include <linux/vgaarb.h>
  41/**
  42 * Get interrupt from bus id.
  43 *
  44 * \param inode device inode.
  45 * \param file_priv DRM file private.
  46 * \param cmd command.
  47 * \param arg user argument, pointing to a drm_irq_busid structure.
  48 * \return zero on success or a negative number on failure.
  49 *
  50 * Finds the PCI device with the specified bus id and gets its IRQ number.
  51 * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
  52 * to that of the device that this DRM instance attached to.
  53 */
  54int drm_irq_by_busid(struct drm_device *dev, void *data,
  55                     struct drm_file *file_priv)
  56{
  57        struct drm_irq_busid *p = data;
  58
  59        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
  60                return -EINVAL;
  61
  62        if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
  63            (p->busnum & 0xff) != dev->pdev->bus->number ||
  64            p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
  65                return -EINVAL;
  66
  67        p->irq = dev->pdev->irq;
  68
  69        DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
  70                  p->irq);
  71
  72        return 0;
  73}
  74
  75static void vblank_disable_fn(unsigned long arg)
  76{
  77        struct drm_device *dev = (struct drm_device *)arg;
  78        unsigned long irqflags;
  79        int i;
  80
  81        if (!dev->vblank_disable_allowed)
  82                return;
  83
  84        for (i = 0; i < dev->num_crtcs; i++) {
  85                spin_lock_irqsave(&dev->vbl_lock, irqflags);
  86                if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
  87                    dev->vblank_enabled[i]) {
  88                        DRM_DEBUG("disabling vblank on crtc %d\n", i);
  89                        dev->last_vblank[i] =
  90                                dev->driver->get_vblank_counter(dev, i);
  91                        dev->driver->disable_vblank(dev, i);
  92                        dev->vblank_enabled[i] = 0;
  93                }
  94                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
  95        }
  96}
  97
  98void drm_vblank_cleanup(struct drm_device *dev)
  99{
 100        /* Bail if the driver didn't call drm_vblank_init() */
 101        if (dev->num_crtcs == 0)
 102                return;
 103
 104        del_timer(&dev->vblank_disable_timer);
 105
 106        vblank_disable_fn((unsigned long)dev);
 107
 108        kfree(dev->vbl_queue);
 109        kfree(dev->_vblank_count);
 110        kfree(dev->vblank_refcount);
 111        kfree(dev->vblank_enabled);
 112        kfree(dev->last_vblank);
 113        kfree(dev->last_vblank_wait);
 114        kfree(dev->vblank_inmodeset);
 115
 116        dev->num_crtcs = 0;
 117}
 118
 119int drm_vblank_init(struct drm_device *dev, int num_crtcs)
 120{
 121        int i, ret = -ENOMEM;
 122
 123        setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
 124                    (unsigned long)dev);
 125        spin_lock_init(&dev->vbl_lock);
 126        dev->num_crtcs = num_crtcs;
 127
 128        dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
 129                                 GFP_KERNEL);
 130        if (!dev->vbl_queue)
 131                goto err;
 132
 133        dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL);
 134        if (!dev->_vblank_count)
 135                goto err;
 136
 137        dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs,
 138                                       GFP_KERNEL);
 139        if (!dev->vblank_refcount)
 140                goto err;
 141
 142        dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
 143        if (!dev->vblank_enabled)
 144                goto err;
 145
 146        dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
 147        if (!dev->last_vblank)
 148                goto err;
 149
 150        dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
 151        if (!dev->last_vblank_wait)
 152                goto err;
 153
 154        dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
 155        if (!dev->vblank_inmodeset)
 156                goto err;
 157
 158        /* Zero per-crtc vblank stuff */
 159        for (i = 0; i < num_crtcs; i++) {
 160                init_waitqueue_head(&dev->vbl_queue[i]);
 161                atomic_set(&dev->_vblank_count[i], 0);
 162                atomic_set(&dev->vblank_refcount[i], 0);
 163        }
 164
 165        dev->vblank_disable_allowed = 0;
 166
 167        return 0;
 168
 169err:
 170        drm_vblank_cleanup(dev);
 171        return ret;
 172}
 173EXPORT_SYMBOL(drm_vblank_init);
 174
 175static void drm_irq_vgaarb_nokms(void *cookie, bool state)
 176{
 177        struct drm_device *dev = cookie;
 178
 179        if (dev->driver->vgaarb_irq) {
 180                dev->driver->vgaarb_irq(dev, state);
 181                return;
 182        }
 183
 184        if (!dev->irq_enabled)
 185                return;
 186
 187        if (state)
 188                dev->driver->irq_uninstall(dev);
 189        else {
 190                dev->driver->irq_preinstall(dev);
 191                dev->driver->irq_postinstall(dev);
 192        }
 193}
 194
 195/**
 196 * Install IRQ handler.
 197 *
 198 * \param dev DRM device.
 199 *
 200 * Initializes the IRQ related data. Installs the handler, calling the driver
 201 * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
 202 * before and after the installation.
 203 */
 204int drm_irq_install(struct drm_device *dev)
 205{
 206        int ret = 0;
 207        unsigned long sh_flags = 0;
 208        char *irqname;
 209
 210        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 211                return -EINVAL;
 212
 213        if (dev->pdev->irq == 0)
 214                return -EINVAL;
 215
 216        mutex_lock(&dev->struct_mutex);
 217
 218        /* Driver must have been initialized */
 219        if (!dev->dev_private) {
 220                mutex_unlock(&dev->struct_mutex);
 221                return -EINVAL;
 222        }
 223
 224        if (dev->irq_enabled) {
 225                mutex_unlock(&dev->struct_mutex);
 226                return -EBUSY;
 227        }
 228        dev->irq_enabled = 1;
 229        mutex_unlock(&dev->struct_mutex);
 230
 231        DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 232
 233        /* Before installing handler */
 234        dev->driver->irq_preinstall(dev);
 235
 236        /* Install handler */
 237        if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
 238                sh_flags = IRQF_SHARED;
 239
 240        if (dev->devname)
 241                irqname = dev->devname;
 242        else
 243                irqname = dev->driver->name;
 244
 245        ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler,
 246                          sh_flags, irqname, dev);
 247
 248        if (ret < 0) {
 249                mutex_lock(&dev->struct_mutex);
 250                dev->irq_enabled = 0;
 251                mutex_unlock(&dev->struct_mutex);
 252                return ret;
 253        }
 254
 255        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 256                vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
 257
 258        /* After installing handler */
 259        ret = dev->driver->irq_postinstall(dev);
 260        if (ret < 0) {
 261                mutex_lock(&dev->struct_mutex);
 262                dev->irq_enabled = 0;
 263                mutex_unlock(&dev->struct_mutex);
 264        }
 265
 266        return ret;
 267}
 268EXPORT_SYMBOL(drm_irq_install);
 269
 270/**
 271 * Uninstall the IRQ handler.
 272 *
 273 * \param dev DRM device.
 274 *
 275 * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
 276 */
 277int drm_irq_uninstall(struct drm_device * dev)
 278{
 279        unsigned long irqflags;
 280        int irq_enabled, i;
 281
 282        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 283                return -EINVAL;
 284
 285        mutex_lock(&dev->struct_mutex);
 286        irq_enabled = dev->irq_enabled;
 287        dev->irq_enabled = 0;
 288        mutex_unlock(&dev->struct_mutex);
 289
 290        /*
 291         * Wake up any waiters so they don't hang.
 292         */
 293        spin_lock_irqsave(&dev->vbl_lock, irqflags);
 294        for (i = 0; i < dev->num_crtcs; i++) {
 295                DRM_WAKEUP(&dev->vbl_queue[i]);
 296                dev->vblank_enabled[i] = 0;
 297                dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
 298        }
 299        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 300
 301        if (!irq_enabled)
 302                return -EINVAL;
 303
 304        DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 305
 306        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 307                vga_client_register(dev->pdev, NULL, NULL, NULL);
 308
 309        dev->driver->irq_uninstall(dev);
 310
 311        free_irq(dev->pdev->irq, dev);
 312
 313        return 0;
 314}
 315EXPORT_SYMBOL(drm_irq_uninstall);
 316
 317/**
 318 * IRQ control ioctl.
 319 *
 320 * \param inode device inode.
 321 * \param file_priv DRM file private.
 322 * \param cmd command.
 323 * \param arg user argument, pointing to a drm_control structure.
 324 * \return zero on success or a negative number on failure.
 325 *
 326 * Calls irq_install() or irq_uninstall() according to \p arg.
 327 */
 328int drm_control(struct drm_device *dev, void *data,
 329                struct drm_file *file_priv)
 330{
 331        struct drm_control *ctl = data;
 332
 333        /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 334
 335
 336        switch (ctl->func) {
 337        case DRM_INST_HANDLER:
 338                if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 339                        return 0;
 340                if (drm_core_check_feature(dev, DRIVER_MODESET))
 341                        return 0;
 342                if (dev->if_version < DRM_IF_VERSION(1, 2) &&
 343                    ctl->irq != dev->pdev->irq)
 344                        return -EINVAL;
 345                return drm_irq_install(dev);
 346        case DRM_UNINST_HANDLER:
 347                if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 348                        return 0;
 349                if (drm_core_check_feature(dev, DRIVER_MODESET))
 350                        return 0;
 351                return drm_irq_uninstall(dev);
 352        default:
 353                return -EINVAL;
 354        }
 355}
 356
 357/**
 358 * drm_vblank_count - retrieve "cooked" vblank counter value
 359 * @dev: DRM device
 360 * @crtc: which counter to retrieve
 361 *
 362 * Fetches the "cooked" vblank count value that represents the number of
 363 * vblank events since the system was booted, including lost events due to
 364 * modesetting activity.
 365 */
 366u32 drm_vblank_count(struct drm_device *dev, int crtc)
 367{
 368        return atomic_read(&dev->_vblank_count[crtc]);
 369}
 370EXPORT_SYMBOL(drm_vblank_count);
 371
 372/**
 373 * drm_update_vblank_count - update the master vblank counter
 374 * @dev: DRM device
 375 * @crtc: counter to update
 376 *
 377 * Call back into the driver to update the appropriate vblank counter
 378 * (specified by @crtc).  Deal with wraparound, if it occurred, and
 379 * update the last read value so we can deal with wraparound on the next
 380 * call if necessary.
 381 *
 382 * Only necessary when going from off->on, to account for frames we
 383 * didn't get an interrupt for.
 384 *
 385 * Note: caller must hold dev->vbl_lock since this reads & writes
 386 * device vblank fields.
 387 */
 388static void drm_update_vblank_count(struct drm_device *dev, int crtc)
 389{
 390        u32 cur_vblank, diff;
 391
 392        /*
 393         * Interrupts were disabled prior to this call, so deal with counter
 394         * wrap if needed.
 395         * NOTE!  It's possible we lost a full dev->max_vblank_count events
 396         * here if the register is small or we had vblank interrupts off for
 397         * a long time.
 398         */
 399        cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
 400        diff = cur_vblank - dev->last_vblank[crtc];
 401        if (cur_vblank < dev->last_vblank[crtc]) {
 402                diff += dev->max_vblank_count;
 403
 404                DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
 405                          crtc, dev->last_vblank[crtc], cur_vblank, diff);
 406        }
 407
 408        DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
 409                  crtc, diff);
 410
 411        atomic_add(diff, &dev->_vblank_count[crtc]);
 412}
 413
 414/**
 415 * drm_vblank_get - get a reference count on vblank events
 416 * @dev: DRM device
 417 * @crtc: which CRTC to own
 418 *
 419 * Acquire a reference count on vblank events to avoid having them disabled
 420 * while in use.
 421 *
 422 * RETURNS
 423 * Zero on success, nonzero on failure.
 424 */
 425int drm_vblank_get(struct drm_device *dev, int crtc)
 426{
 427        unsigned long irqflags;
 428        int ret = 0;
 429
 430        spin_lock_irqsave(&dev->vbl_lock, irqflags);
 431        /* Going from 0->1 means we have to enable interrupts again */
 432        if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
 433            !dev->vblank_enabled[crtc]) {
 434                ret = dev->driver->enable_vblank(dev, crtc);
 435                DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
 436                if (ret)
 437                        atomic_dec(&dev->vblank_refcount[crtc]);
 438                else {
 439                        dev->vblank_enabled[crtc] = 1;
 440                        drm_update_vblank_count(dev, crtc);
 441                }
 442        }
 443        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 444
 445        return ret;
 446}
 447EXPORT_SYMBOL(drm_vblank_get);
 448
 449/**
 450 * drm_vblank_put - give up ownership of vblank events
 451 * @dev: DRM device
 452 * @crtc: which counter to give up
 453 *
 454 * Release ownership of a given vblank counter, turning off interrupts
 455 * if possible.
 456 */
 457void drm_vblank_put(struct drm_device *dev, int crtc)
 458{
 459        BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
 460
 461        /* Last user schedules interrupt disable */
 462        if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
 463                mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
 464}
 465EXPORT_SYMBOL(drm_vblank_put);
 466
 467/**
 468 * drm_vblank_pre_modeset - account for vblanks across mode sets
 469 * @dev: DRM device
 470 * @crtc: CRTC in question
 471 * @post: post or pre mode set?
 472 *
 473 * Account for vblank events across mode setting events, which will likely
 474 * reset the hardware frame counter.
 475 */
 476void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 477{
 478        /*
 479         * To avoid all the problems that might happen if interrupts
 480         * were enabled/disabled around or between these calls, we just
 481         * have the kernel take a reference on the CRTC (just once though
 482         * to avoid corrupting the count if multiple, mismatch calls occur),
 483         * so that interrupts remain enabled in the interim.
 484         */
 485        if (!dev->vblank_inmodeset[crtc]) {
 486                dev->vblank_inmodeset[crtc] = 0x1;
 487                if (drm_vblank_get(dev, crtc) == 0)
 488                        dev->vblank_inmodeset[crtc] |= 0x2;
 489        }
 490}
 491EXPORT_SYMBOL(drm_vblank_pre_modeset);
 492
 493void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
 494{
 495        unsigned long irqflags;
 496
 497        if (dev->vblank_inmodeset[crtc]) {
 498                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 499                dev->vblank_disable_allowed = 1;
 500                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 501
 502                if (dev->vblank_inmodeset[crtc] & 0x2)
 503                        drm_vblank_put(dev, crtc);
 504
 505                dev->vblank_inmodeset[crtc] = 0;
 506        }
 507}
 508EXPORT_SYMBOL(drm_vblank_post_modeset);
 509
 510/**
 511 * drm_modeset_ctl - handle vblank event counter changes across mode switch
 512 * @DRM_IOCTL_ARGS: standard ioctl arguments
 513 *
 514 * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
 515 * ioctls around modesetting so that any lost vblank events are accounted for.
 516 *
 517 * Generally the counter will reset across mode sets.  If interrupts are
 518 * enabled around this call, we don't have to do anything since the counter
 519 * will have already been incremented.
 520 */
 521int drm_modeset_ctl(struct drm_device *dev, void *data,
 522                    struct drm_file *file_priv)
 523{
 524        struct drm_modeset_ctl *modeset = data;
 525        int crtc, ret = 0;
 526
 527        /* If drm_vblank_init() hasn't been called yet, just no-op */
 528        if (!dev->num_crtcs)
 529                goto out;
 530
 531        crtc = modeset->crtc;
 532        if (crtc >= dev->num_crtcs) {
 533                ret = -EINVAL;
 534                goto out;
 535        }
 536
 537        switch (modeset->cmd) {
 538        case _DRM_PRE_MODESET:
 539                drm_vblank_pre_modeset(dev, crtc);
 540                break;
 541        case _DRM_POST_MODESET:
 542                drm_vblank_post_modeset(dev, crtc);
 543                break;
 544        default:
 545                ret = -EINVAL;
 546                break;
 547        }
 548
 549out:
 550        return ret;
 551}
 552
 553/**
 554 * Wait for VBLANK.
 555 *
 556 * \param inode device inode.
 557 * \param file_priv DRM file private.
 558 * \param cmd command.
 559 * \param data user argument, pointing to a drm_wait_vblank structure.
 560 * \return zero on success or a negative number on failure.
 561 *
 562 * This function enables the vblank interrupt on the pipe requested, then
 563 * sleeps waiting for the requested sequence number to occur, and drops
 564 * the vblank interrupt refcount afterwards. (vblank irq disable follows that
 565 * after a timeout with no further vblank waits scheduled).
 566 */
 567int drm_wait_vblank(struct drm_device *dev, void *data,
 568                    struct drm_file *file_priv)
 569{
 570        union drm_wait_vblank *vblwait = data;
 571        int ret = 0;
 572        unsigned int flags, seq, crtc;
 573
 574        if ((!dev->pdev->irq) || (!dev->irq_enabled))
 575                return -EINVAL;
 576
 577        if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
 578                return -EINVAL;
 579
 580        if (vblwait->request.type &
 581            ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
 582                DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
 583                          vblwait->request.type,
 584                          (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
 585                return -EINVAL;
 586        }
 587
 588        flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
 589        crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 590
 591        if (crtc >= dev->num_crtcs)
 592                return -EINVAL;
 593
 594        ret = drm_vblank_get(dev, crtc);
 595        if (ret) {
 596                DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
 597                return ret;
 598        }
 599        seq = drm_vblank_count(dev, crtc);
 600
 601        switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
 602        case _DRM_VBLANK_RELATIVE:
 603                vblwait->request.sequence += seq;
 604                vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
 605        case _DRM_VBLANK_ABSOLUTE:
 606                break;
 607        default:
 608                ret = -EINVAL;
 609                goto done;
 610        }
 611
 612        if ((flags & _DRM_VBLANK_NEXTONMISS) &&
 613            (seq - vblwait->request.sequence) <= (1<<23)) {
 614                vblwait->request.sequence = seq + 1;
 615        }
 616
 617        DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
 618                  vblwait->request.sequence, crtc);
 619        dev->last_vblank_wait[crtc] = vblwait->request.sequence;
 620        DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
 621                    (((drm_vblank_count(dev, crtc) -
 622                       vblwait->request.sequence) <= (1 << 23)) ||
 623                     !dev->irq_enabled));
 624
 625        if (ret != -EINTR) {
 626                struct timeval now;
 627
 628                do_gettimeofday(&now);
 629
 630                vblwait->reply.tval_sec = now.tv_sec;
 631                vblwait->reply.tval_usec = now.tv_usec;
 632                vblwait->reply.sequence = drm_vblank_count(dev, crtc);
 633                DRM_DEBUG("returning %d to client\n",
 634                          vblwait->reply.sequence);
 635        } else {
 636                DRM_DEBUG("vblank wait interrupted by signal\n");
 637        }
 638
 639done:
 640        drm_vblank_put(dev, crtc);
 641        return ret;
 642}
 643
 644/**
 645 * drm_handle_vblank - handle a vblank event
 646 * @dev: DRM device
 647 * @crtc: where this event occurred
 648 *
 649 * Drivers should call this routine in their vblank interrupt handlers to
 650 * update the vblank counter and send any signals that may be pending.
 651 */
 652void drm_handle_vblank(struct drm_device *dev, int crtc)
 653{
 654        atomic_inc(&dev->_vblank_count[crtc]);
 655        DRM_WAKEUP(&dev->vbl_queue[crtc]);
 656}
 657EXPORT_SYMBOL(drm_handle_vblank);
 658
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.