drm_irq.c revision 194965
1145132Sanholt/*- 2145132Sanholt * Copyright 2003 Eric Anholt 3145132Sanholt * All Rights Reserved. 4145132Sanholt * 5145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 6145132Sanholt * copy of this software and associated documentation files (the "Software"), 7145132Sanholt * to deal in the Software without restriction, including without limitation 8145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 10145132Sanholt * Software is furnished to do so, subject to the following conditions: 11145132Sanholt * 12145132Sanholt * The above copyright notice and this permission notice (including the next 13145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 14145132Sanholt * Software. 15145132Sanholt * 16145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19145132Sanholt * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22145132Sanholt * 23145132Sanholt * Authors: 24145132Sanholt * Eric Anholt <anholt@FreeBSD.org> 25145132Sanholt * 26145132Sanholt */ 27145132Sanholt 28152909Sanholt#include <sys/cdefs.h> 29152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/drm_irq.c 194965 2009-06-25 15:36:11Z rnoland $"); 30152909Sanholt 31182080Srnoland/** @file drm_irq.c 32182080Srnoland * Support code for handling setup/teardown of interrupt handlers and 33182080Srnoland * handing interrupt handlers off to the drivers. 34182080Srnoland */ 35182080Srnoland 36145132Sanholt#include "dev/drm/drmP.h" 37145132Sanholt#include "dev/drm/drm.h" 38145132Sanholt 39182080Srnolandint drm_irq_by_busid(struct drm_device *dev, void *data, 40182080Srnoland struct drm_file *file_priv) 41145132Sanholt{ 42183573Srnoland struct drm_irq_busid *irq = data; 43145132Sanholt 44182080Srnoland if ((irq->busnum >> 8) != dev->pci_domain || 45182080Srnoland (irq->busnum & 0xff) != dev->pci_bus || 46182080Srnoland irq->devnum != dev->pci_slot || 47182080Srnoland irq->funcnum != dev->pci_func) 48145132Sanholt return EINVAL; 49145132Sanholt 50182080Srnoland irq->irq = dev->irq; 51145132Sanholt 52145132Sanholt DRM_DEBUG("%d:%d:%d => IRQ %d\n", 53183573Srnoland irq->busnum, irq->devnum, irq->funcnum, irq->irq); 54145132Sanholt 55145132Sanholt return 0; 56145132Sanholt} 57145132Sanholt 58145132Sanholtstatic irqreturn_t 59145132Sanholtdrm_irq_handler_wrap(DRM_IRQ_ARGS) 60145132Sanholt{ 61182080Srnoland struct drm_device *dev = arg; 62145132Sanholt 63145132Sanholt DRM_SPINLOCK(&dev->irq_lock); 64183573Srnoland dev->driver->irq_handler(arg); 65145132Sanholt DRM_SPINUNLOCK(&dev->irq_lock); 66145132Sanholt} 67145132Sanholt 68182080Srnolandstatic void vblank_disable_fn(void *arg) 69145132Sanholt{ 70182080Srnoland struct drm_device *dev = (struct drm_device *)arg; 71182080Srnoland int i; 72182080Srnoland 73194960Srnoland /* Make sure that we are called with the lock held */ 74194960Srnoland mtx_assert(&dev->vbl_lock, MA_OWNED); 75194960Srnoland 76182080Srnoland if (callout_pending(&dev->vblank_disable_timer)) { 77182080Srnoland /* callout was reset */ 78182080Srnoland return; 79182080Srnoland } 80182080Srnoland if (!callout_active(&dev->vblank_disable_timer)) { 81182080Srnoland /* callout was stopped */ 82182080Srnoland return; 83182080Srnoland } 84182080Srnoland callout_deactivate(&dev->vblank_disable_timer); 85182080Srnoland 86190401Srnoland DRM_DEBUG("vblank_disable: %s\n", dev->vblank_disable_allowed ? 87190401Srnoland "allowed" : "denied"); 88182080Srnoland if (!dev->vblank_disable_allowed) 89182080Srnoland return; 90182080Srnoland 91182080Srnoland for (i = 0; i < dev->num_crtcs; i++) { 92194965Srnoland if (dev->vblank[i].refcount == 0 && 93190401Srnoland dev->vblank[i].enabled && !dev->vblank[i].inmodeset) { 94182080Srnoland DRM_DEBUG("disabling vblank on crtc %d\n", i); 95182080Srnoland dev->vblank[i].last = 96183573Srnoland dev->driver->get_vblank_counter(dev, i); 97183573Srnoland dev->driver->disable_vblank(dev, i); 98182080Srnoland dev->vblank[i].enabled = 0; 99182080Srnoland } 100182080Srnoland } 101182080Srnoland} 102182080Srnoland 103189130Srnolandvoid drm_vblank_cleanup(struct drm_device *dev) 104182080Srnoland{ 105182080Srnoland /* Bail if the driver didn't call drm_vblank_init() */ 106182080Srnoland if (dev->num_crtcs == 0) 107183573Srnoland return; 108182080Srnoland 109190022Srnoland DRM_SPINLOCK(&dev->vbl_lock); 110182080Srnoland callout_stop(&dev->vblank_disable_timer); 111190022Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 112182080Srnoland 113182080Srnoland callout_drain(&dev->vblank_disable_timer); 114182080Srnoland 115194960Srnoland DRM_SPINLOCK(&dev->vbl_lock); 116182080Srnoland vblank_disable_fn((void *)dev); 117194960Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 118182080Srnoland 119183833Srnoland free(dev->vblank, DRM_MEM_DRIVER); 120182080Srnoland 121182080Srnoland dev->num_crtcs = 0; 122182080Srnoland} 123182080Srnoland 124182080Srnolandint drm_vblank_init(struct drm_device *dev, int num_crtcs) 125182080Srnoland{ 126182080Srnoland int i, ret = ENOMEM; 127182080Srnoland 128182080Srnoland callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0); 129182080Srnoland dev->num_crtcs = num_crtcs; 130182080Srnoland 131183833Srnoland dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs, 132183833Srnoland DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 133182080Srnoland if (!dev->vblank) 134182080Srnoland goto err; 135182080Srnoland 136183573Srnoland DRM_DEBUG("\n"); 137183573Srnoland 138182080Srnoland /* Zero per-crtc vblank stuff */ 139194963Srnoland DRM_SPINLOCK(&dev->vbl_lock); 140182080Srnoland for (i = 0; i < num_crtcs; i++) { 141182080Srnoland DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); 142194963Srnoland dev->vblank[i].refcount = 0; 143194963Srnoland atomic_set_rel_32(&dev->vblank[i].count, 0); 144182080Srnoland } 145182080Srnoland dev->vblank_disable_allowed = 0; 146194963Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 147182080Srnoland 148182080Srnoland return 0; 149182080Srnoland 150182080Srnolanderr: 151182080Srnoland drm_vblank_cleanup(dev); 152182080Srnoland return ret; 153182080Srnoland} 154182080Srnoland 155182080Srnolandint drm_irq_install(struct drm_device *dev) 156182080Srnoland{ 157190401Srnoland int crtc, retcode; 158145132Sanholt 159145132Sanholt if (dev->irq == 0 || dev->dev_private == NULL) 160182080Srnoland return EINVAL; 161145132Sanholt 162183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 163145132Sanholt 164145132Sanholt DRM_LOCK(); 165145132Sanholt if (dev->irq_enabled) { 166145132Sanholt DRM_UNLOCK(); 167182080Srnoland return EBUSY; 168145132Sanholt } 169145132Sanholt dev->irq_enabled = 1; 170145132Sanholt 171145132Sanholt dev->context_flag = 0; 172145132Sanholt 173183573Srnoland /* Before installing handler */ 174183573Srnoland dev->driver->irq_preinstall(dev); 175145132Sanholt DRM_UNLOCK(); 176145132Sanholt 177183573Srnoland /* Install handler */ 178182080Srnoland#if __FreeBSD_version >= 700031 179182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 180182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 181182080Srnoland NULL, drm_irq_handler_wrap, dev, &dev->irqh); 182145132Sanholt#else 183182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 184182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 185182080Srnoland drm_irq_handler_wrap, dev, &dev->irqh); 186145132Sanholt#endif 187145132Sanholt if (retcode != 0) 188145132Sanholt goto err; 189145132Sanholt 190183573Srnoland /* After installing handler */ 191145132Sanholt DRM_LOCK(); 192183573Srnoland dev->driver->irq_postinstall(dev); 193145132Sanholt DRM_UNLOCK(); 194190401Srnoland if (dev->driver->enable_vblank) { 195190401Srnoland DRM_SPINLOCK(&dev->vbl_lock); 196190401Srnoland for( crtc = 0 ; crtc < dev->num_crtcs ; crtc++) { 197190401Srnoland if (dev->driver->enable_vblank(dev, crtc) == 0) { 198190401Srnoland dev->vblank[crtc].enabled = 1; 199190401Srnoland } 200190401Srnoland } 201190401Srnoland callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 202190401Srnoland (timeout_t *)vblank_disable_fn, (void *)dev); 203190401Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 204190401Srnoland } 205145132Sanholt 206145132Sanholt return 0; 207145132Sanholterr: 208145132Sanholt DRM_LOCK(); 209145132Sanholt dev->irq_enabled = 0; 210145132Sanholt DRM_UNLOCK(); 211189052Srnoland 212145132Sanholt return retcode; 213145132Sanholt} 214145132Sanholt 215182080Srnolandint drm_irq_uninstall(struct drm_device *dev) 216145132Sanholt{ 217190022Srnoland int crtc; 218190022Srnoland 219145132Sanholt if (!dev->irq_enabled) 220182080Srnoland return EINVAL; 221145132Sanholt 222145132Sanholt dev->irq_enabled = 0; 223145132Sanholt 224190022Srnoland /* 225190022Srnoland * Wake up any waiters so they don't hang. 226190022Srnoland */ 227190022Srnoland DRM_SPINLOCK(&dev->vbl_lock); 228190022Srnoland for (crtc = 0; crtc < dev->num_crtcs; crtc++) { 229190125Srnoland if (dev->vblank[crtc].enabled) { 230190125Srnoland DRM_WAKEUP(&dev->vblank[crtc].queue); 231190401Srnoland dev->vblank[crtc].last = 232190401Srnoland dev->driver->get_vblank_counter(dev, crtc); 233190125Srnoland dev->vblank[crtc].enabled = 0; 234190125Srnoland } 235190022Srnoland } 236190022Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 237190022Srnoland 238183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 239145132Sanholt 240183573Srnoland dev->driver->irq_uninstall(dev); 241145132Sanholt 242145132Sanholt DRM_UNLOCK(); 243145132Sanholt bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 244145132Sanholt DRM_LOCK(); 245183573Srnoland 246145132Sanholt return 0; 247145132Sanholt} 248145132Sanholt 249182080Srnolandint drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) 250145132Sanholt{ 251183573Srnoland struct drm_control *ctl = data; 252145132Sanholt int err; 253145132Sanholt 254183573Srnoland switch (ctl->func) { 255145132Sanholt case DRM_INST_HANDLER: 256145132Sanholt /* Handle drivers whose DRM used to require IRQ setup but the 257145132Sanholt * no longer does. 258145132Sanholt */ 259183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 260145132Sanholt return 0; 261145132Sanholt if (dev->if_version < DRM_IF_VERSION(1, 2) && 262182080Srnoland ctl->irq != dev->irq) 263182080Srnoland return EINVAL; 264145132Sanholt return drm_irq_install(dev); 265145132Sanholt case DRM_UNINST_HANDLER: 266183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 267145132Sanholt return 0; 268145132Sanholt DRM_LOCK(); 269145132Sanholt err = drm_irq_uninstall(dev); 270145132Sanholt DRM_UNLOCK(); 271145132Sanholt return err; 272145132Sanholt default: 273182080Srnoland return EINVAL; 274145132Sanholt } 275145132Sanholt} 276145132Sanholt 277182080Srnolandu32 drm_vblank_count(struct drm_device *dev, int crtc) 278145132Sanholt{ 279194963Srnoland return atomic_load_acq_32(&dev->vblank[crtc].count); 280182080Srnoland} 281145132Sanholt 282182080Srnolandstatic void drm_update_vblank_count(struct drm_device *dev, int crtc) 283182080Srnoland{ 284182080Srnoland u32 cur_vblank, diff; 285182080Srnoland 286182080Srnoland /* 287182080Srnoland * Interrupts were disabled prior to this call, so deal with counter 288182080Srnoland * wrap if needed. 289182080Srnoland * NOTE! It's possible we lost a full dev->max_vblank_count events 290182080Srnoland * here if the register is small or we had vblank interrupts off for 291182080Srnoland * a long time. 292182080Srnoland */ 293183573Srnoland cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 294182080Srnoland diff = cur_vblank - dev->vblank[crtc].last; 295182080Srnoland if (cur_vblank < dev->vblank[crtc].last) { 296182080Srnoland diff += dev->max_vblank_count; 297182080Srnoland 298183573Srnoland DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n", 299182080Srnoland crtc, dev->vblank[crtc].last, cur_vblank, diff); 300182080Srnoland } 301182080Srnoland 302182080Srnoland DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 303182080Srnoland crtc, diff); 304182080Srnoland 305194963Srnoland atomic_add_rel_32(&dev->vblank[crtc].count, diff); 306182080Srnoland} 307182080Srnoland 308182080Srnolandint drm_vblank_get(struct drm_device *dev, int crtc) 309182080Srnoland{ 310182080Srnoland int ret = 0; 311182080Srnoland 312194963Srnoland /* Make sure that we are called with the lock held */ 313194963Srnoland mtx_assert(&dev->vbl_lock, MA_OWNED); 314194963Srnoland 315182080Srnoland /* Going from 0->1 means we have to enable interrupts again */ 316194963Srnoland if (++dev->vblank[crtc].refcount == 1 && 317182080Srnoland !dev->vblank[crtc].enabled) { 318183573Srnoland ret = dev->driver->enable_vblank(dev, crtc); 319190022Srnoland DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); 320182080Srnoland if (ret) 321194963Srnoland --dev->vblank[crtc].refcount; 322182080Srnoland else { 323182080Srnoland dev->vblank[crtc].enabled = 1; 324182080Srnoland drm_update_vblank_count(dev, crtc); 325182080Srnoland } 326182080Srnoland } 327182080Srnoland 328182080Srnoland return ret; 329182080Srnoland} 330182080Srnoland 331182080Srnolandvoid drm_vblank_put(struct drm_device *dev, int crtc) 332182080Srnoland{ 333194963Srnoland /* Make sure that we are called with the lock held */ 334194963Srnoland mtx_assert(&dev->vbl_lock, MA_OWNED); 335194963Srnoland 336194963Srnoland KASSERT(dev->vblank[crtc].refcount > 0, 337190022Srnoland ("invalid refcount")); 338182080Srnoland 339182080Srnoland /* Last user schedules interrupt disable */ 340194963Srnoland if (--dev->vblank[crtc].refcount == 0) 341182080Srnoland callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 342182080Srnoland (timeout_t *)vblank_disable_fn, (void *)dev); 343182080Srnoland} 344182080Srnoland 345182080Srnolandint drm_modeset_ctl(struct drm_device *dev, void *data, 346182080Srnoland struct drm_file *file_priv) 347182080Srnoland{ 348182080Srnoland struct drm_modeset_ctl *modeset = data; 349182080Srnoland int crtc, ret = 0; 350182080Srnoland 351182080Srnoland /* If drm_vblank_init() hasn't been called yet, just no-op */ 352182080Srnoland if (!dev->num_crtcs) 353183573Srnoland goto out; 354182080Srnoland 355182080Srnoland crtc = modeset->crtc; 356182080Srnoland if (crtc >= dev->num_crtcs) { 357182080Srnoland ret = EINVAL; 358182080Srnoland goto out; 359182080Srnoland } 360182080Srnoland 361182080Srnoland /* 362182080Srnoland * To avoid all the problems that might happen if interrupts 363182080Srnoland * were enabled/disabled around or between these calls, we just 364182080Srnoland * have the kernel take a reference on the CRTC (just once though 365182080Srnoland * to avoid corrupting the count if multiple, mismatch calls occur), 366182080Srnoland * so that interrupts remain enabled in the interim. 367182080Srnoland */ 368182080Srnoland switch (modeset->cmd) { 369182080Srnoland case _DRM_PRE_MODESET: 370194963Srnoland DRM_DEBUG("pre-modeset, crtc %d\n", crtc); 371194963Srnoland DRM_SPINLOCK(&dev->vbl_lock); 372182080Srnoland if (!dev->vblank[crtc].inmodeset) { 373190022Srnoland dev->vblank[crtc].inmodeset = 0x1; 374190022Srnoland if (drm_vblank_get(dev, crtc) == 0) 375190022Srnoland dev->vblank[crtc].inmodeset |= 0x2; 376182080Srnoland } 377194963Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 378182080Srnoland break; 379182080Srnoland case _DRM_POST_MODESET: 380194963Srnoland DRM_DEBUG("post-modeset, crtc %d\n", crtc); 381194963Srnoland DRM_SPINLOCK(&dev->vbl_lock); 382182080Srnoland if (dev->vblank[crtc].inmodeset) { 383190022Srnoland if (dev->vblank[crtc].inmodeset & 0x2) 384190022Srnoland drm_vblank_put(dev, crtc); 385182080Srnoland dev->vblank[crtc].inmodeset = 0; 386182080Srnoland } 387194963Srnoland dev->vblank_disable_allowed = 1; 388194963Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 389182080Srnoland break; 390182080Srnoland default: 391182080Srnoland ret = EINVAL; 392182080Srnoland break; 393182080Srnoland } 394182080Srnoland 395182080Srnolandout: 396182080Srnoland return ret; 397182080Srnoland} 398182080Srnoland 399182080Srnolandint drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) 400182080Srnoland{ 401183573Srnoland union drm_wait_vblank *vblwait = data; 402189050Srnoland unsigned int flags, seq, crtc; 403182080Srnoland int ret = 0; 404182080Srnoland 405145132Sanholt if (!dev->irq_enabled) 406182080Srnoland return EINVAL; 407145132Sanholt 408182080Srnoland if (vblwait->request.type & 409182080Srnoland ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 410182080Srnoland DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 411182080Srnoland vblwait->request.type, 412182080Srnoland (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 413182080Srnoland return EINVAL; 414182080Srnoland } 415145132Sanholt 416182080Srnoland flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 417182080Srnoland crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 418182080Srnoland 419182080Srnoland if (crtc >= dev->num_crtcs) 420182080Srnoland return EINVAL; 421182080Srnoland 422194963Srnoland DRM_SPINLOCK(&dev->vbl_lock); 423182080Srnoland ret = drm_vblank_get(dev, crtc); 424194963Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 425189050Srnoland if (ret) { 426189050Srnoland DRM_ERROR("failed to acquire vblank counter, %d\n", ret); 427183573Srnoland return ret; 428189050Srnoland } 429182080Srnoland seq = drm_vblank_count(dev, crtc); 430182080Srnoland 431182080Srnoland switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 432182080Srnoland case _DRM_VBLANK_RELATIVE: 433182080Srnoland vblwait->request.sequence += seq; 434182080Srnoland vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 435182080Srnoland case _DRM_VBLANK_ABSOLUTE: 436182080Srnoland break; 437182080Srnoland default: 438182080Srnoland ret = EINVAL; 439182080Srnoland goto done; 440145132Sanholt } 441145132Sanholt 442182080Srnoland if ((flags & _DRM_VBLANK_NEXTONMISS) && 443182080Srnoland (seq - vblwait->request.sequence) <= (1<<23)) { 444182080Srnoland vblwait->request.sequence = seq + 1; 445182080Srnoland } 446182080Srnoland 447145132Sanholt if (flags & _DRM_VBLANK_SIGNAL) { 448194748Srnoland /* There have never been any consumers */ 449145132Sanholt ret = EINVAL; 450145132Sanholt } else { 451189050Srnoland DRM_DEBUG("waiting on vblank count %d, crtc %d\n", 452189050Srnoland vblwait->request.sequence, crtc); 453190401Srnoland for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) - 454190401Srnoland vblwait->request.sequence) <= (1 << 23)) || 455190401Srnoland !dev->irq_enabled) ; ) { 456190433Srnoland mtx_lock(&dev->irq_lock); 457190433Srnoland if (!(((drm_vblank_count(dev, crtc) - 458190433Srnoland vblwait->request.sequence) <= (1 << 23)) || 459190433Srnoland !dev->irq_enabled)) 460190433Srnoland ret = mtx_sleep(&dev->vblank[crtc].queue, 461190433Srnoland &dev->irq_lock, PCATCH, "vblwtq", 462194746Srnoland DRM_HZ); 463190433Srnoland mtx_unlock(&dev->irq_lock); 464189050Srnoland } 465182080Srnoland 466190401Srnoland if (ret != EINTR && ret != ERESTART) { 467182080Srnoland struct timeval now; 468182080Srnoland 469182080Srnoland microtime(&now); 470182080Srnoland vblwait->reply.tval_sec = now.tv_sec; 471182080Srnoland vblwait->reply.tval_usec = now.tv_usec; 472182080Srnoland vblwait->reply.sequence = drm_vblank_count(dev, crtc); 473190401Srnoland DRM_DEBUG("returning %d to client, irq_enabled %d\n", 474190401Srnoland vblwait->reply.sequence, dev->irq_enabled); 475189050Srnoland } else { 476189050Srnoland DRM_DEBUG("vblank wait interrupted by signal\n"); 477182080Srnoland } 478145132Sanholt } 479145132Sanholt 480182080Srnolanddone: 481194963Srnoland DRM_SPINLOCK(&dev->vbl_lock); 482182080Srnoland drm_vblank_put(dev, crtc); 483194963Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 484194963Srnoland 485145132Sanholt return ret; 486145132Sanholt} 487145132Sanholt 488182080Srnolandvoid drm_handle_vblank(struct drm_device *dev, int crtc) 489182080Srnoland{ 490194963Srnoland atomic_add_rel_32(&dev->vblank[crtc].count, 1); 491182080Srnoland DRM_WAKEUP(&dev->vblank[crtc].queue); 492182080Srnoland} 493182080Srnoland 494