drm_irq.c revision 189052
176116Sdcs/*- 276116Sdcs * Copyright 2003 Eric Anholt 376116Sdcs * All Rights Reserved. 476116Sdcs * 576116Sdcs * Permission is hereby granted, free of charge, to any person obtaining a 694290Sdcs * copy of this software and associated documentation files (the "Software"), 776116Sdcs * to deal in the Software without restriction, including without limitation 876116Sdcs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 976116Sdcs * and/or sell copies of the Software, and to permit persons to whom the 1076116Sdcs * Software is furnished to do so, subject to the following conditions: 1176116Sdcs * 1276116Sdcs * The above copyright notice and this permission notice (including the next 1376116Sdcs * paragraph) shall be included in all copies or substantial portions of the 1494290Sdcs * Software. 1594290Sdcs * 1694290Sdcs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1794290Sdcs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1894290Sdcs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1976116Sdcs * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 2076116Sdcs * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2176116Sdcs * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2276116Sdcs * 2376116Sdcs * Authors: 2476116Sdcs * Eric Anholt <anholt@FreeBSD.org> 2576116Sdcs * 2676116Sdcs */ 2776116Sdcs 2876116Sdcs#include <sys/cdefs.h> 2976116Sdcs__FBSDID("$FreeBSD: head/sys/dev/drm/drm_irq.c 189052 2009-02-25 18:54:35Z rnoland $"); 3076116Sdcs 3176116Sdcs/** @file drm_irq.c 3276116Sdcs * Support code for handling setup/teardown of interrupt handlers and 3376116Sdcs * handing interrupt handlers off to the drivers. 3476116Sdcs */ 3576116Sdcs 3676116Sdcs#include "dev/drm/drmP.h" 3776116Sdcs#include "dev/drm/drm.h" 3876116Sdcs 3976116Sdcsint drm_irq_by_busid(struct drm_device *dev, void *data, 4076116Sdcs struct drm_file *file_priv) 4194290Sdcs{ 4294290Sdcs struct drm_irq_busid *irq = data; 4394290Sdcs 4494290Sdcs if ((irq->busnum >> 8) != dev->pci_domain || 4594290Sdcs (irq->busnum & 0xff) != dev->pci_bus || 4694290Sdcs irq->devnum != dev->pci_slot || 4794290Sdcs irq->funcnum != dev->pci_func) 4894290Sdcs return EINVAL; 4994290Sdcs 5076116Sdcs irq->irq = dev->irq; 5194290Sdcs 5294290Sdcs DRM_DEBUG("%d:%d:%d => IRQ %d\n", 5394290Sdcs irq->busnum, irq->devnum, irq->funcnum, irq->irq); 5494290Sdcs 5576116Sdcs return 0; 5676116Sdcs} 5776116Sdcs 5876116Sdcsstatic irqreturn_t 5976116Sdcsdrm_irq_handler_wrap(DRM_IRQ_ARGS) 6076116Sdcs{ 6176116Sdcs struct drm_device *dev = arg; 6276116Sdcs 6376116Sdcs DRM_SPINLOCK(&dev->irq_lock); 6476116Sdcs dev->driver->irq_handler(arg); 6576116Sdcs DRM_SPINUNLOCK(&dev->irq_lock); 6676116Sdcs} 6776116Sdcs 6876116Sdcsstatic void vblank_disable_fn(void *arg) 6976116Sdcs{ 7076116Sdcs struct drm_device *dev = (struct drm_device *)arg; 7176116Sdcs int i; 7276116Sdcs 7376116Sdcs if (callout_pending(&dev->vblank_disable_timer)) { 7476116Sdcs /* callout was reset */ 7576116Sdcs return; 7694290Sdcs } 7776116Sdcs if (!callout_active(&dev->vblank_disable_timer)) { 7876116Sdcs /* callout was stopped */ 7976116Sdcs return; 8094290Sdcs } 8194290Sdcs callout_deactivate(&dev->vblank_disable_timer); 8294290Sdcs 8376116Sdcs DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed); 8494290Sdcs if (!dev->vblank_disable_allowed) 8594290Sdcs return; 8676116Sdcs 8794290Sdcs for (i = 0; i < dev->num_crtcs; i++) { 8876116Sdcs if (atomic_read(&dev->vblank[i].refcount) == 0 && 8994290Sdcs dev->vblank[i].enabled) { 9076116Sdcs DRM_DEBUG("disabling vblank on crtc %d\n", i); 9176116Sdcs dev->vblank[i].last = 9276116Sdcs dev->driver->get_vblank_counter(dev, i); 9376116Sdcs dev->driver->disable_vblank(dev, i); 9476116Sdcs dev->vblank[i].enabled = 0; 9576116Sdcs } 9694290Sdcs } 9794290Sdcs} 9894290Sdcs 9994290Sdcsstatic void drm_vblank_cleanup(struct drm_device *dev) 10094290Sdcs{ 10194290Sdcs unsigned long irqflags; 10294290Sdcs 10394290Sdcs /* Bail if the driver didn't call drm_vblank_init() */ 10494290Sdcs if (dev->num_crtcs == 0) 10594290Sdcs return; 10694290Sdcs 10776116Sdcs DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 10876116Sdcs callout_stop(&dev->vblank_disable_timer); 10976116Sdcs DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 11076116Sdcs 11176116Sdcs callout_drain(&dev->vblank_disable_timer); 11294290Sdcs 11394290Sdcs vblank_disable_fn((void *)dev); 11476116Sdcs 11576116Sdcs free(dev->vblank, DRM_MEM_DRIVER); 11676116Sdcs 11776116Sdcs dev->num_crtcs = 0; 11876116Sdcs} 11976116Sdcs 12076116Sdcsint drm_vblank_init(struct drm_device *dev, int num_crtcs) 12176116Sdcs{ 12294290Sdcs int i, ret = ENOMEM; 12394290Sdcs 12494290Sdcs callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0); 12594290Sdcs atomic_set(&dev->vbl_signal_pending, 0); 12694290Sdcs dev->num_crtcs = num_crtcs; 12794290Sdcs 12894290Sdcs dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs, 12994290Sdcs DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 13094290Sdcs if (!dev->vblank) 13194290Sdcs goto err; 13276116Sdcs 13376116Sdcs DRM_DEBUG("\n"); 13476116Sdcs 13594290Sdcs /* Zero per-crtc vblank stuff */ 13676116Sdcs for (i = 0; i < num_crtcs; i++) { 13776116Sdcs DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); 13876116Sdcs TAILQ_INIT(&dev->vblank[i].sigs); 13976116Sdcs atomic_set(&dev->vblank[i].count, 0); 14076116Sdcs atomic_set(&dev->vblank[i].refcount, 0); 14194290Sdcs } 14276116Sdcs 14376116Sdcs dev->vblank_disable_allowed = 0; 14476116Sdcs 14594290Sdcs return 0; 14694290Sdcs 14794290Sdcserr: 14894290Sdcs drm_vblank_cleanup(dev); 14994290Sdcs return ret; 15094290Sdcs} 15194290Sdcs 15294290Sdcsint drm_irq_install(struct drm_device *dev) 15394290Sdcs{ 15494290Sdcs int retcode; 15594290Sdcs 15694290Sdcs if (dev->irq == 0 || dev->dev_private == NULL) 15794290Sdcs return EINVAL; 15894290Sdcs 15994290Sdcs DRM_DEBUG("irq=%d\n", dev->irq); 16094290Sdcs 16194290Sdcs DRM_LOCK(); 16294290Sdcs if (dev->irq_enabled) { 16394290Sdcs DRM_UNLOCK(); 16494290Sdcs return EBUSY; 16594290Sdcs } 16694290Sdcs dev->irq_enabled = 1; 16794290Sdcs 16894290Sdcs dev->context_flag = 0; 16994290Sdcs 17094290Sdcs /* Before installing handler */ 17194290Sdcs dev->driver->irq_preinstall(dev); 17294290Sdcs DRM_UNLOCK(); 17394290Sdcs 17494290Sdcs /* Install handler */ 17576116Sdcs#if __FreeBSD_version >= 700031 17676116Sdcs retcode = bus_setup_intr(dev->device, dev->irqr, 17776116Sdcs INTR_TYPE_TTY | INTR_MPSAFE, 17876116Sdcs NULL, drm_irq_handler_wrap, dev, &dev->irqh); 17976116Sdcs#else 18076116Sdcs retcode = bus_setup_intr(dev->device, dev->irqr, 18176116Sdcs INTR_TYPE_TTY | INTR_MPSAFE, 18276116Sdcs drm_irq_handler_wrap, dev, &dev->irqh); 18376116Sdcs#endif 18476116Sdcs if (retcode != 0) 18576116Sdcs goto err; 18676116Sdcs 18776116Sdcs /* After installing handler */ 18876116Sdcs DRM_LOCK(); 18994290Sdcs dev->driver->irq_postinstall(dev); 19094290Sdcs DRM_UNLOCK(); 19194290Sdcs 19294290Sdcs return 0; 19376116Sdcserr: 19476116Sdcs DRM_LOCK(); 19576116Sdcs dev->irq_enabled = 0; 19676116Sdcs DRM_UNLOCK(); 19776116Sdcs 19876116Sdcs return retcode; 19994290Sdcs} 20094290Sdcs 20194290Sdcsint drm_irq_uninstall(struct drm_device *dev) 20294290Sdcs{ 20394290Sdcs if (!dev->irq_enabled) 204264262Semaste return EINVAL; 20594290Sdcs 20694290Sdcs dev->irq_enabled = 0; 20776116Sdcs 20876116Sdcs DRM_DEBUG("irq=%d\n", dev->irq); 20976116Sdcs 21076116Sdcs dev->driver->irq_uninstall(dev); 21176116Sdcs 21276116Sdcs DRM_UNLOCK(); 21376116Sdcs bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 21476116Sdcs DRM_LOCK(); 21594290Sdcs 21676116Sdcs drm_vblank_cleanup(dev); 21776116Sdcs 21894290Sdcs return 0; 219249223Skientzle} 22076116Sdcs 22176116Sdcsint drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) 222249223Skientzle{ 223249223Skientzle struct drm_control *ctl = data; 22476116Sdcs int err; 22576116Sdcs 22676116Sdcs switch (ctl->func) { 22776116Sdcs case DRM_INST_HANDLER: 22876116Sdcs /* Handle drivers whose DRM used to require IRQ setup but the 22994290Sdcs * no longer does. 23076116Sdcs */ 23176116Sdcs if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 23294290Sdcs return 0; 23394290Sdcs if (dev->if_version < DRM_IF_VERSION(1, 2) && 23494290Sdcs ctl->irq != dev->irq) 23594290Sdcs return EINVAL; 23694290Sdcs return drm_irq_install(dev); 23794290Sdcs case DRM_UNINST_HANDLER: 23894290Sdcs if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 23976116Sdcs return 0; 24076116Sdcs DRM_LOCK(); 24176116Sdcs err = drm_irq_uninstall(dev); 242264262Semaste DRM_UNLOCK(); 24376116Sdcs return err; 244264262Semaste default: 24594290Sdcs return EINVAL; 24676116Sdcs } 24776116Sdcs} 248167850Sjkim 249264262Semasteu32 drm_vblank_count(struct drm_device *dev, int crtc) 250167850Sjkim{ 251264262Semaste return atomic_read(&dev->vblank[crtc].count); 25276116Sdcs} 253264262Semaste 25476116Sdcsstatic void drm_update_vblank_count(struct drm_device *dev, int crtc) 25576116Sdcs{ 256167850Sjkim u32 cur_vblank, diff; 257167850Sjkim 258264262Semaste /* 259167850Sjkim * Interrupts were disabled prior to this call, so deal with counter 260167850Sjkim * wrap if needed. 26176116Sdcs * NOTE! It's possible we lost a full dev->max_vblank_count events 26276116Sdcs * here if the register is small or we had vblank interrupts off for 263264262Semaste * a long time. 26476116Sdcs */ 26576116Sdcs cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 26676116Sdcs diff = cur_vblank - dev->vblank[crtc].last; 267264262Semaste if (cur_vblank < dev->vblank[crtc].last) { 26876116Sdcs diff += dev->max_vblank_count; 26976116Sdcs 27076116Sdcs DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n", 271264262Semaste crtc, dev->vblank[crtc].last, cur_vblank, diff); 27276116Sdcs } 27376116Sdcs 27476116Sdcs DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 275264262Semaste crtc, diff); 27676116Sdcs 27776116Sdcs atomic_add(diff, &dev->vblank[crtc].count); 27894290Sdcs} 27976116Sdcs 28076116Sdcsint drm_vblank_get(struct drm_device *dev, int crtc) 28176116Sdcs{ 28276116Sdcs unsigned long irqflags; 28376116Sdcs int ret = 0; 28476116Sdcs 285249223Skientzle DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 28676116Sdcs /* Going from 0->1 means we have to enable interrupts again */ 28794290Sdcs atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); 28894290Sdcs DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 28976116Sdcs if (dev->vblank[crtc].refcount == 1 && 29076116Sdcs !dev->vblank[crtc].enabled) { 29176116Sdcs ret = dev->driver->enable_vblank(dev, crtc); 29276116Sdcs if (ret) 29376116Sdcs atomic_dec(&dev->vblank[crtc].refcount); 29476116Sdcs else { 29576116Sdcs dev->vblank[crtc].enabled = 1; 29676116Sdcs drm_update_vblank_count(dev, crtc); 29776116Sdcs } 29876116Sdcs } 29976116Sdcs DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 30076116Sdcs 30176116Sdcs return ret; 30276116Sdcs} 30376116Sdcs 30476116Sdcsvoid drm_vblank_put(struct drm_device *dev, int crtc) 30576116Sdcs{ 30676116Sdcs unsigned long irqflags; 30776116Sdcs 30876116Sdcs DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 30976116Sdcs /* Last user schedules interrupt disable */ 31076116Sdcs atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); 31176116Sdcs DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 31276116Sdcs if (dev->vblank[crtc].refcount == 0) 31376116Sdcs callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 31476116Sdcs (timeout_t *)vblank_disable_fn, (void *)dev); 31576116Sdcs DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 31676116Sdcs} 31776116Sdcs 31876116Sdcsint drm_modeset_ctl(struct drm_device *dev, void *data, 31976116Sdcs struct drm_file *file_priv) 32076116Sdcs{ 32176116Sdcs struct drm_modeset_ctl *modeset = data; 32276116Sdcs unsigned long irqflags; 32376116Sdcs int crtc, ret = 0; 32476116Sdcs 32576116Sdcs DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs); 32676116Sdcs /* If drm_vblank_init() hasn't been called yet, just no-op */ 32776116Sdcs if (!dev->num_crtcs) 328249223Skientzle goto out; 329249223Skientzle 33076116Sdcs crtc = modeset->crtc; 33176116Sdcs DRM_DEBUG("crtc=%d\n", crtc); 33276116Sdcs if (crtc >= dev->num_crtcs) { 33394290Sdcs ret = EINVAL; 33476116Sdcs goto out; 335249223Skientzle } 336249223Skientzle 33776116Sdcs /* 33876116Sdcs * To avoid all the problems that might happen if interrupts 33994290Sdcs * were enabled/disabled around or between these calls, we just 34076116Sdcs * have the kernel take a reference on the CRTC (just once though 34176116Sdcs * to avoid corrupting the count if multiple, mismatch calls occur), 342249223Skientzle * so that interrupts remain enabled in the interim. 343249223Skientzle */ 34476116Sdcs switch (modeset->cmd) { 34576116Sdcs case _DRM_PRE_MODESET: 34676116Sdcs DRM_DEBUG("pre-modeset\n"); 34794290Sdcs if (!dev->vblank[crtc].inmodeset) { 34894290Sdcs dev->vblank[crtc].inmodeset = 1; 34976116Sdcs drm_vblank_get(dev, crtc); 35076116Sdcs } 35176116Sdcs break; 35276116Sdcs case _DRM_POST_MODESET: 35376116Sdcs DRM_DEBUG("post-modeset\n"); 35476116Sdcs if (dev->vblank[crtc].inmodeset) { 35576116Sdcs DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 35676116Sdcs dev->vblank_disable_allowed = 1; 35776116Sdcs dev->vblank[crtc].inmodeset = 0; 35876116Sdcs DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 35976116Sdcs drm_vblank_put(dev, crtc); 36076116Sdcs } 36176116Sdcs break; 36276116Sdcs default: 36376116Sdcs ret = EINVAL; 36476116Sdcs break; 36576116Sdcs } 36676116Sdcs 36776116Sdcsout: 36876116Sdcs return ret; 36976116Sdcs} 37076116Sdcs 37176116Sdcsint drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) 37276116Sdcs{ 37376116Sdcs union drm_wait_vblank *vblwait = data; 37476116Sdcs unsigned int flags, seq, crtc; 37576116Sdcs int ret = 0; 37676116Sdcs 37776116Sdcs if (!dev->irq_enabled) 37876116Sdcs return EINVAL; 37976116Sdcs 38076116Sdcs if (vblwait->request.type & 38176116Sdcs ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 38276116Sdcs DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 38376116Sdcs vblwait->request.type, 38476116Sdcs (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 38576116Sdcs return EINVAL; 38676116Sdcs } 38776116Sdcs 38876116Sdcs flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 38976116Sdcs crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 39076116Sdcs 39176116Sdcs if (crtc >= dev->num_crtcs) 39276116Sdcs return EINVAL; 39376116Sdcs 39476116Sdcs ret = drm_vblank_get(dev, crtc); 39576116Sdcs if (ret) { 39676116Sdcs DRM_ERROR("failed to acquire vblank counter, %d\n", ret); 39776116Sdcs return ret; 39894290Sdcs } 39976116Sdcs seq = drm_vblank_count(dev, crtc); 40076116Sdcs 40176116Sdcs switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 40276116Sdcs case _DRM_VBLANK_RELATIVE: 40376116Sdcs vblwait->request.sequence += seq; 40476116Sdcs vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 40576116Sdcs case _DRM_VBLANK_ABSOLUTE: 40676116Sdcs break; 40776116Sdcs default: 40876116Sdcs ret = EINVAL; 40976116Sdcs goto done; 41076116Sdcs } 41176116Sdcs 41276116Sdcs if ((flags & _DRM_VBLANK_NEXTONMISS) && 41376116Sdcs (seq - vblwait->request.sequence) <= (1<<23)) { 41476116Sdcs vblwait->request.sequence = seq + 1; 41576116Sdcs } 41676116Sdcs 41776116Sdcs if (flags & _DRM_VBLANK_SIGNAL) { 41876116Sdcs#if 0 /* disabled */ 41976116Sdcs drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), 42076116Sdcs DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 42176116Sdcs if (vbl_sig == NULL) 42276116Sdcs return ENOMEM; 42376116Sdcs 42476116Sdcs vbl_sig->sequence = vblwait->request.sequence; 42576116Sdcs vbl_sig->signo = vblwait->request.signal; 42676116Sdcs vbl_sig->pid = DRM_CURRENTPID; 42776116Sdcs 42894290Sdcs vblwait->reply.sequence = atomic_read(&dev->vbl_received); 42976116Sdcs 43076116Sdcs DRM_SPINLOCK(&dev->vbl_lock); 43176116Sdcs TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); 43276116Sdcs DRM_SPINUNLOCK(&dev->vbl_lock); 43376116Sdcs ret = 0; 43476116Sdcs#endif 43576116Sdcs ret = EINVAL; 43676116Sdcs } else { 43776116Sdcs DRM_DEBUG("waiting on vblank count %d, crtc %d\n", 43876116Sdcs vblwait->request.sequence, crtc); 43976116Sdcs for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - 44076116Sdcs vblwait->request.sequence) <= (1 << 23)) ; ) { 44176116Sdcs mtx_lock(&dev->irq_lock); 44276116Sdcs if (!((drm_vblank_count(dev, crtc) - 44376116Sdcs vblwait->request.sequence) <= (1 << 23))) 44476116Sdcs ret = mtx_sleep(&dev->vblank[crtc].queue, 44594290Sdcs &dev->irq_lock, PCATCH, "vblwtq", 44676116Sdcs 3 * DRM_HZ); 44776116Sdcs mtx_unlock(&dev->irq_lock); 44876116Sdcs } 44976116Sdcs 45076116Sdcs DRM_DEBUG("return = %d\n", ret); 45176116Sdcs if (ret != EINTR) { 45276116Sdcs struct timeval now; 45376116Sdcs 45476116Sdcs microtime(&now); 45576116Sdcs vblwait->reply.tval_sec = now.tv_sec; 45676116Sdcs vblwait->reply.tval_usec = now.tv_usec; 45776116Sdcs vblwait->reply.sequence = drm_vblank_count(dev, crtc); 45876116Sdcs DRM_DEBUG("returning %d to client\n", 45994290Sdcs vblwait->reply.sequence); 46094290Sdcs } else { 46176116Sdcs DRM_DEBUG("vblank wait interrupted by signal\n"); 46276116Sdcs } 46376116Sdcs } 46476116Sdcs 46576116Sdcsdone: 46676116Sdcs drm_vblank_put(dev, crtc); 46776116Sdcs return ret; 46876116Sdcs} 46976116Sdcs 47076116Sdcsvoid drm_vbl_send_signals(struct drm_device *dev, int crtc) 47176116Sdcs{ 47276116Sdcs} 47376116Sdcs 47476116Sdcs#if 0 /* disabled */ 47576116Sdcsvoid drm_vbl_send_signals(struct drm_device *dev, int crtc ) 47676116Sdcs{ 47776116Sdcs drm_vbl_sig_t *vbl_sig; 47876116Sdcs unsigned int vbl_seq = atomic_read( &dev->vbl_received ); 47976116Sdcs struct proc *p; 48076116Sdcs 48176116Sdcs vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); 48276116Sdcs while (vbl_sig != NULL) { 48376116Sdcs drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); 48476116Sdcs 48576116Sdcs if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { 48676116Sdcs p = pfind(vbl_sig->pid); 48776116Sdcs if (p != NULL) 48876116Sdcs psignal(p, vbl_sig->signo); 48976116Sdcs 49076116Sdcs TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); 49176116Sdcs DRM_FREE(vbl_sig,sizeof(*vbl_sig)); 49276116Sdcs } 49376116Sdcs vbl_sig = next; 49476116Sdcs } 49576116Sdcs} 49676116Sdcs#endif 49794290Sdcs 49894290Sdcsvoid drm_handle_vblank(struct drm_device *dev, int crtc) 49976116Sdcs{ 50076116Sdcs atomic_inc(&dev->vblank[crtc].count); 50176116Sdcs DRM_WAKEUP(&dev->vblank[crtc].queue); 50276116Sdcs drm_vbl_send_signals(dev, crtc); 50376116Sdcs} 50494290Sdcs 50594290Sdcs