drm_irq.c revision 189052
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 189052 2009-02-25 18:54:35Z 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 73182080Srnoland if (callout_pending(&dev->vblank_disable_timer)) { 74182080Srnoland /* callout was reset */ 75182080Srnoland return; 76182080Srnoland } 77182080Srnoland if (!callout_active(&dev->vblank_disable_timer)) { 78182080Srnoland /* callout was stopped */ 79182080Srnoland return; 80182080Srnoland } 81182080Srnoland callout_deactivate(&dev->vblank_disable_timer); 82182080Srnoland 83183573Srnoland DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed); 84182080Srnoland if (!dev->vblank_disable_allowed) 85182080Srnoland return; 86182080Srnoland 87182080Srnoland for (i = 0; i < dev->num_crtcs; i++) { 88182080Srnoland if (atomic_read(&dev->vblank[i].refcount) == 0 && 89182080Srnoland dev->vblank[i].enabled) { 90182080Srnoland DRM_DEBUG("disabling vblank on crtc %d\n", i); 91182080Srnoland dev->vblank[i].last = 92183573Srnoland dev->driver->get_vblank_counter(dev, i); 93183573Srnoland dev->driver->disable_vblank(dev, i); 94182080Srnoland dev->vblank[i].enabled = 0; 95182080Srnoland } 96182080Srnoland } 97182080Srnoland} 98182080Srnoland 99182080Srnolandstatic void drm_vblank_cleanup(struct drm_device *dev) 100182080Srnoland{ 101182080Srnoland unsigned long irqflags; 102182080Srnoland 103182080Srnoland /* Bail if the driver didn't call drm_vblank_init() */ 104182080Srnoland if (dev->num_crtcs == 0) 105183573Srnoland return; 106182080Srnoland 107182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 108182080Srnoland callout_stop(&dev->vblank_disable_timer); 109182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 110182080Srnoland 111182080Srnoland callout_drain(&dev->vblank_disable_timer); 112182080Srnoland 113182080Srnoland vblank_disable_fn((void *)dev); 114182080Srnoland 115183833Srnoland free(dev->vblank, DRM_MEM_DRIVER); 116182080Srnoland 117182080Srnoland dev->num_crtcs = 0; 118182080Srnoland} 119182080Srnoland 120182080Srnolandint drm_vblank_init(struct drm_device *dev, int num_crtcs) 121182080Srnoland{ 122182080Srnoland int i, ret = ENOMEM; 123182080Srnoland 124182080Srnoland callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0); 125182080Srnoland atomic_set(&dev->vbl_signal_pending, 0); 126182080Srnoland dev->num_crtcs = num_crtcs; 127182080Srnoland 128183833Srnoland dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs, 129183833Srnoland DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 130182080Srnoland if (!dev->vblank) 131182080Srnoland goto err; 132182080Srnoland 133183573Srnoland DRM_DEBUG("\n"); 134183573Srnoland 135182080Srnoland /* Zero per-crtc vblank stuff */ 136182080Srnoland for (i = 0; i < num_crtcs; i++) { 137182080Srnoland DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); 138182080Srnoland TAILQ_INIT(&dev->vblank[i].sigs); 139182080Srnoland atomic_set(&dev->vblank[i].count, 0); 140182080Srnoland atomic_set(&dev->vblank[i].refcount, 0); 141182080Srnoland } 142182080Srnoland 143182080Srnoland dev->vblank_disable_allowed = 0; 144182080Srnoland 145182080Srnoland return 0; 146182080Srnoland 147182080Srnolanderr: 148182080Srnoland drm_vblank_cleanup(dev); 149182080Srnoland return ret; 150182080Srnoland} 151182080Srnoland 152182080Srnolandint drm_irq_install(struct drm_device *dev) 153182080Srnoland{ 154145132Sanholt int retcode; 155145132Sanholt 156145132Sanholt if (dev->irq == 0 || dev->dev_private == NULL) 157182080Srnoland return EINVAL; 158145132Sanholt 159183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 160145132Sanholt 161145132Sanholt DRM_LOCK(); 162145132Sanholt if (dev->irq_enabled) { 163145132Sanholt DRM_UNLOCK(); 164182080Srnoland return EBUSY; 165145132Sanholt } 166145132Sanholt dev->irq_enabled = 1; 167145132Sanholt 168145132Sanholt dev->context_flag = 0; 169145132Sanholt 170183573Srnoland /* Before installing handler */ 171183573Srnoland dev->driver->irq_preinstall(dev); 172145132Sanholt DRM_UNLOCK(); 173145132Sanholt 174183573Srnoland /* Install handler */ 175182080Srnoland#if __FreeBSD_version >= 700031 176182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 177182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 178182080Srnoland NULL, drm_irq_handler_wrap, dev, &dev->irqh); 179145132Sanholt#else 180182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 181182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 182182080Srnoland drm_irq_handler_wrap, dev, &dev->irqh); 183145132Sanholt#endif 184145132Sanholt if (retcode != 0) 185145132Sanholt goto err; 186145132Sanholt 187183573Srnoland /* After installing handler */ 188145132Sanholt DRM_LOCK(); 189183573Srnoland dev->driver->irq_postinstall(dev); 190145132Sanholt DRM_UNLOCK(); 191145132Sanholt 192145132Sanholt return 0; 193145132Sanholterr: 194145132Sanholt DRM_LOCK(); 195145132Sanholt dev->irq_enabled = 0; 196145132Sanholt DRM_UNLOCK(); 197189052Srnoland 198145132Sanholt return retcode; 199145132Sanholt} 200145132Sanholt 201182080Srnolandint drm_irq_uninstall(struct drm_device *dev) 202145132Sanholt{ 203145132Sanholt if (!dev->irq_enabled) 204182080Srnoland return EINVAL; 205145132Sanholt 206145132Sanholt dev->irq_enabled = 0; 207145132Sanholt 208183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 209145132Sanholt 210183573Srnoland dev->driver->irq_uninstall(dev); 211145132Sanholt 212145132Sanholt DRM_UNLOCK(); 213145132Sanholt bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 214145132Sanholt DRM_LOCK(); 215183573Srnoland 216182080Srnoland drm_vblank_cleanup(dev); 217145132Sanholt 218145132Sanholt return 0; 219145132Sanholt} 220145132Sanholt 221182080Srnolandint drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) 222145132Sanholt{ 223183573Srnoland struct drm_control *ctl = data; 224145132Sanholt int err; 225145132Sanholt 226183573Srnoland switch (ctl->func) { 227145132Sanholt case DRM_INST_HANDLER: 228145132Sanholt /* Handle drivers whose DRM used to require IRQ setup but the 229145132Sanholt * no longer does. 230145132Sanholt */ 231183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 232145132Sanholt return 0; 233145132Sanholt if (dev->if_version < DRM_IF_VERSION(1, 2) && 234182080Srnoland ctl->irq != dev->irq) 235182080Srnoland return EINVAL; 236145132Sanholt return drm_irq_install(dev); 237145132Sanholt case DRM_UNINST_HANDLER: 238183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 239145132Sanholt return 0; 240145132Sanholt DRM_LOCK(); 241145132Sanholt err = drm_irq_uninstall(dev); 242145132Sanholt DRM_UNLOCK(); 243145132Sanholt return err; 244145132Sanholt default: 245182080Srnoland return EINVAL; 246145132Sanholt } 247145132Sanholt} 248145132Sanholt 249182080Srnolandu32 drm_vblank_count(struct drm_device *dev, int crtc) 250145132Sanholt{ 251182080Srnoland return atomic_read(&dev->vblank[crtc].count); 252182080Srnoland} 253145132Sanholt 254182080Srnolandstatic void drm_update_vblank_count(struct drm_device *dev, int crtc) 255182080Srnoland{ 256182080Srnoland u32 cur_vblank, diff; 257182080Srnoland 258182080Srnoland /* 259182080Srnoland * Interrupts were disabled prior to this call, so deal with counter 260182080Srnoland * wrap if needed. 261182080Srnoland * NOTE! It's possible we lost a full dev->max_vblank_count events 262182080Srnoland * here if the register is small or we had vblank interrupts off for 263182080Srnoland * a long time. 264182080Srnoland */ 265183573Srnoland cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 266182080Srnoland diff = cur_vblank - dev->vblank[crtc].last; 267182080Srnoland if (cur_vblank < dev->vblank[crtc].last) { 268182080Srnoland diff += dev->max_vblank_count; 269182080Srnoland 270183573Srnoland DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n", 271182080Srnoland crtc, dev->vblank[crtc].last, cur_vblank, diff); 272182080Srnoland } 273182080Srnoland 274182080Srnoland DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 275182080Srnoland crtc, diff); 276182080Srnoland 277182080Srnoland atomic_add(diff, &dev->vblank[crtc].count); 278182080Srnoland} 279182080Srnoland 280182080Srnolandint drm_vblank_get(struct drm_device *dev, int crtc) 281182080Srnoland{ 282182080Srnoland unsigned long irqflags; 283182080Srnoland int ret = 0; 284182080Srnoland 285182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 286182080Srnoland /* Going from 0->1 means we have to enable interrupts again */ 287182080Srnoland atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); 288189050Srnoland DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 289182080Srnoland if (dev->vblank[crtc].refcount == 1 && 290182080Srnoland !dev->vblank[crtc].enabled) { 291183573Srnoland ret = dev->driver->enable_vblank(dev, crtc); 292182080Srnoland if (ret) 293182080Srnoland atomic_dec(&dev->vblank[crtc].refcount); 294182080Srnoland else { 295182080Srnoland dev->vblank[crtc].enabled = 1; 296182080Srnoland drm_update_vblank_count(dev, crtc); 297182080Srnoland } 298182080Srnoland } 299182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 300182080Srnoland 301182080Srnoland return ret; 302182080Srnoland} 303182080Srnoland 304182080Srnolandvoid drm_vblank_put(struct drm_device *dev, int crtc) 305182080Srnoland{ 306182080Srnoland unsigned long irqflags; 307182080Srnoland 308182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 309182080Srnoland /* Last user schedules interrupt disable */ 310182080Srnoland atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); 311189050Srnoland DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 312182080Srnoland if (dev->vblank[crtc].refcount == 0) 313182080Srnoland callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 314182080Srnoland (timeout_t *)vblank_disable_fn, (void *)dev); 315182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 316182080Srnoland} 317182080Srnoland 318182080Srnolandint drm_modeset_ctl(struct drm_device *dev, void *data, 319182080Srnoland struct drm_file *file_priv) 320182080Srnoland{ 321182080Srnoland struct drm_modeset_ctl *modeset = data; 322182080Srnoland unsigned long irqflags; 323182080Srnoland int crtc, ret = 0; 324182080Srnoland 325183573Srnoland DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs); 326182080Srnoland /* If drm_vblank_init() hasn't been called yet, just no-op */ 327182080Srnoland if (!dev->num_crtcs) 328183573Srnoland goto out; 329182080Srnoland 330182080Srnoland crtc = modeset->crtc; 331183573Srnoland DRM_DEBUG("crtc=%d\n", crtc); 332182080Srnoland if (crtc >= dev->num_crtcs) { 333182080Srnoland ret = EINVAL; 334182080Srnoland goto out; 335182080Srnoland } 336182080Srnoland 337182080Srnoland /* 338182080Srnoland * To avoid all the problems that might happen if interrupts 339182080Srnoland * were enabled/disabled around or between these calls, we just 340182080Srnoland * have the kernel take a reference on the CRTC (just once though 341182080Srnoland * to avoid corrupting the count if multiple, mismatch calls occur), 342182080Srnoland * so that interrupts remain enabled in the interim. 343182080Srnoland */ 344182080Srnoland switch (modeset->cmd) { 345182080Srnoland case _DRM_PRE_MODESET: 346183573Srnoland DRM_DEBUG("pre-modeset\n"); 347182080Srnoland if (!dev->vblank[crtc].inmodeset) { 348182080Srnoland dev->vblank[crtc].inmodeset = 1; 349182080Srnoland drm_vblank_get(dev, crtc); 350182080Srnoland } 351182080Srnoland break; 352182080Srnoland case _DRM_POST_MODESET: 353183573Srnoland DRM_DEBUG("post-modeset\n"); 354182080Srnoland if (dev->vblank[crtc].inmodeset) { 355182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 356182080Srnoland dev->vblank_disable_allowed = 1; 357182080Srnoland dev->vblank[crtc].inmodeset = 0; 358182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 359182080Srnoland drm_vblank_put(dev, crtc); 360182080Srnoland } 361182080Srnoland break; 362182080Srnoland default: 363182080Srnoland ret = EINVAL; 364182080Srnoland break; 365182080Srnoland } 366182080Srnoland 367182080Srnolandout: 368182080Srnoland return ret; 369182080Srnoland} 370182080Srnoland 371182080Srnolandint drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) 372182080Srnoland{ 373183573Srnoland union drm_wait_vblank *vblwait = data; 374189050Srnoland unsigned int flags, seq, crtc; 375182080Srnoland int ret = 0; 376182080Srnoland 377145132Sanholt if (!dev->irq_enabled) 378182080Srnoland return EINVAL; 379145132Sanholt 380182080Srnoland if (vblwait->request.type & 381182080Srnoland ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 382182080Srnoland DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 383182080Srnoland vblwait->request.type, 384182080Srnoland (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 385182080Srnoland return EINVAL; 386182080Srnoland } 387145132Sanholt 388182080Srnoland flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 389182080Srnoland crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 390182080Srnoland 391182080Srnoland if (crtc >= dev->num_crtcs) 392182080Srnoland return EINVAL; 393182080Srnoland 394182080Srnoland ret = drm_vblank_get(dev, crtc); 395189050Srnoland if (ret) { 396189050Srnoland DRM_ERROR("failed to acquire vblank counter, %d\n", ret); 397183573Srnoland return ret; 398189050Srnoland } 399182080Srnoland seq = drm_vblank_count(dev, crtc); 400182080Srnoland 401182080Srnoland switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 402182080Srnoland case _DRM_VBLANK_RELATIVE: 403182080Srnoland vblwait->request.sequence += seq; 404182080Srnoland vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 405182080Srnoland case _DRM_VBLANK_ABSOLUTE: 406182080Srnoland break; 407182080Srnoland default: 408182080Srnoland ret = EINVAL; 409182080Srnoland goto done; 410145132Sanholt } 411145132Sanholt 412182080Srnoland if ((flags & _DRM_VBLANK_NEXTONMISS) && 413182080Srnoland (seq - vblwait->request.sequence) <= (1<<23)) { 414182080Srnoland vblwait->request.sequence = seq + 1; 415182080Srnoland } 416182080Srnoland 417145132Sanholt if (flags & _DRM_VBLANK_SIGNAL) { 418145132Sanholt#if 0 /* disabled */ 419183833Srnoland drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), 420183833Srnoland DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 421145132Sanholt if (vbl_sig == NULL) 422145132Sanholt return ENOMEM; 423145132Sanholt 424182080Srnoland vbl_sig->sequence = vblwait->request.sequence; 425182080Srnoland vbl_sig->signo = vblwait->request.signal; 426145132Sanholt vbl_sig->pid = DRM_CURRENTPID; 427145132Sanholt 428182080Srnoland vblwait->reply.sequence = atomic_read(&dev->vbl_received); 429145132Sanholt 430182080Srnoland DRM_SPINLOCK(&dev->vbl_lock); 431145132Sanholt TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); 432182080Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 433145132Sanholt ret = 0; 434145132Sanholt#endif 435145132Sanholt ret = EINVAL; 436145132Sanholt } else { 437189050Srnoland DRM_DEBUG("waiting on vblank count %d, crtc %d\n", 438189050Srnoland vblwait->request.sequence, crtc); 439189050Srnoland for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - 440189050Srnoland vblwait->request.sequence) <= (1 << 23)) ; ) { 441189050Srnoland mtx_lock(&dev->irq_lock); 442189050Srnoland if (!((drm_vblank_count(dev, crtc) - 443189050Srnoland vblwait->request.sequence) <= (1 << 23))) 444189050Srnoland ret = mtx_sleep(&dev->vblank[crtc].queue, 445189050Srnoland &dev->irq_lock, PCATCH, "vblwtq", 446189050Srnoland 3 * DRM_HZ); 447189050Srnoland mtx_unlock(&dev->irq_lock); 448189050Srnoland } 449182080Srnoland 450189050Srnoland DRM_DEBUG("return = %d\n", ret); 451182080Srnoland if (ret != EINTR) { 452182080Srnoland struct timeval now; 453182080Srnoland 454182080Srnoland microtime(&now); 455182080Srnoland vblwait->reply.tval_sec = now.tv_sec; 456182080Srnoland vblwait->reply.tval_usec = now.tv_usec; 457182080Srnoland vblwait->reply.sequence = drm_vblank_count(dev, crtc); 458189050Srnoland DRM_DEBUG("returning %d to client\n", 459189050Srnoland vblwait->reply.sequence); 460189050Srnoland } else { 461189050Srnoland DRM_DEBUG("vblank wait interrupted by signal\n"); 462182080Srnoland } 463145132Sanholt } 464145132Sanholt 465182080Srnolanddone: 466182080Srnoland drm_vblank_put(dev, crtc); 467145132Sanholt return ret; 468145132Sanholt} 469145132Sanholt 470182080Srnolandvoid drm_vbl_send_signals(struct drm_device *dev, int crtc) 471145132Sanholt{ 472145132Sanholt} 473145132Sanholt 474145132Sanholt#if 0 /* disabled */ 475182080Srnolandvoid drm_vbl_send_signals(struct drm_device *dev, int crtc ) 476145132Sanholt{ 477145132Sanholt drm_vbl_sig_t *vbl_sig; 478145132Sanholt unsigned int vbl_seq = atomic_read( &dev->vbl_received ); 479145132Sanholt struct proc *p; 480145132Sanholt 481145132Sanholt vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); 482145132Sanholt while (vbl_sig != NULL) { 483145132Sanholt drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); 484145132Sanholt 485183573Srnoland if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { 486145132Sanholt p = pfind(vbl_sig->pid); 487145132Sanholt if (p != NULL) 488145132Sanholt psignal(p, vbl_sig->signo); 489145132Sanholt 490145132Sanholt TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); 491145132Sanholt DRM_FREE(vbl_sig,sizeof(*vbl_sig)); 492145132Sanholt } 493145132Sanholt vbl_sig = next; 494145132Sanholt } 495145132Sanholt} 496145132Sanholt#endif 497182080Srnoland 498182080Srnolandvoid drm_handle_vblank(struct drm_device *dev, int crtc) 499182080Srnoland{ 500182080Srnoland atomic_inc(&dev->vblank[crtc].count); 501182080Srnoland DRM_WAKEUP(&dev->vblank[crtc].queue); 502182080Srnoland drm_vbl_send_signals(dev, crtc); 503182080Srnoland} 504182080Srnoland 505