Date: Tue, 23 Jun 2009 15:59:10 +0000 (UTC) From: Robert Noland <rnoland@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r194728 - in stable/7/sys: . contrib/pf dev/drm Message-ID: <200906231559.n5NFxA44081861@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rnoland Date: Tue Jun 23 15:59:10 2009 New Revision: 194728 URL: http://svn.freebsd.org/changeset/base/194728 Log: Merge 190401 from HEAD Rework the management of vblank interrupts a bit. When a vt switch occurs the irq handler is uninstalled. Interrupts and the state tracking of what was enabled/disabled wasn't working properly. This should resolve the reports of "slow windows" after a vt switch, among other things. The radeon 2d driver seems to work a bit more correctly than the Intel driver. With the Intel driver, vblank interrupts will be enabled at system startup and will only be disabled after an additional modeset (vt switch, dpms, randr event). With this patch, I am able to run glxgears synced to vblank and vt switch while it is running without ill effects. (Still didn't fix the slow window issues on Intel) Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/drm/drm_irq.c Modified: stable/7/sys/dev/drm/drm_irq.c ============================================================================== --- stable/7/sys/dev/drm/drm_irq.c Tue Jun 23 15:56:10 2009 (r194727) +++ stable/7/sys/dev/drm/drm_irq.c Tue Jun 23 15:59:10 2009 (r194728) @@ -80,13 +80,14 @@ static void vblank_disable_fn(void *arg) } callout_deactivate(&dev->vblank_disable_timer); - DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed); + DRM_DEBUG("vblank_disable: %s\n", dev->vblank_disable_allowed ? + "allowed" : "denied"); if (!dev->vblank_disable_allowed) return; for (i = 0; i < dev->num_crtcs; i++) { if (atomic_read(&dev->vblank[i].refcount) == 0 && - dev->vblank[i].enabled) { + dev->vblank[i].enabled && !dev->vblank[i].inmodeset) { DRM_DEBUG("disabling vblank on crtc %d\n", i); dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); @@ -149,7 +150,7 @@ err: int drm_irq_install(struct drm_device *dev) { - int retcode; + int crtc, retcode; if (dev->irq == 0 || dev->dev_private == NULL) return EINVAL; @@ -186,6 +187,17 @@ int drm_irq_install(struct drm_device *d DRM_LOCK(); dev->driver->irq_postinstall(dev); DRM_UNLOCK(); + if (dev->driver->enable_vblank) { + DRM_SPINLOCK(&dev->vbl_lock); + for( crtc = 0 ; crtc < dev->num_crtcs ; crtc++) { + if (dev->driver->enable_vblank(dev, crtc) == 0) { + dev->vblank[crtc].enabled = 1; + } + } + callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, + (timeout_t *)vblank_disable_fn, (void *)dev); + DRM_SPINUNLOCK(&dev->vbl_lock); + } return 0; err: @@ -212,9 +224,9 @@ int drm_irq_uninstall(struct drm_device for (crtc = 0; crtc < dev->num_crtcs; crtc++) { if (dev->vblank[crtc].enabled) { DRM_WAKEUP(&dev->vblank[crtc].queue); - dev->vblank[crtc].enabled = 0; dev->vblank[crtc].last = - dev->driver->get_vblank_counter(dev, crtc); + dev->driver->get_vblank_counter(dev, crtc); + dev->vblank[crtc].enabled = 0; } } DRM_SPINUNLOCK(&dev->vbl_lock); @@ -320,9 +332,11 @@ void drm_vblank_put(struct drm_device *d /* Last user schedules interrupt disable */ atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); + DRM_SPINLOCK(&dev->vbl_lock); if (dev->vblank[crtc].refcount == 0) callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, (timeout_t *)vblank_disable_fn, (void *)dev); + DRM_SPINUNLOCK(&dev->vbl_lock); } int drm_modeset_ctl(struct drm_device *dev, void *data, @@ -449,31 +463,26 @@ int drm_wait_vblank(struct drm_device *d } else { DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); - for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23)) ; ) { - mtx_lock(&dev->irq_lock); - if (!((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23))) - ret = mtx_sleep(&dev->vblank[crtc].queue, - &dev->irq_lock, PCATCH, "vblwtq", - 3 * DRM_HZ); - mtx_unlock(&dev->irq_lock); - } - - if (ret == ERESTART) { - DRM_DEBUG("restarting syscall\n"); - return ret; + mtx_lock(&dev->irq_lock); + dev->vblank[crtc].last = vblwait->request.sequence; + for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) - + vblwait->request.sequence) <= (1 << 23)) || + !dev->irq_enabled) ; ) { + ret = mtx_sleep(&dev->vblank[crtc].queue, + &dev->irq_lock, PCATCH, "vblwtq", + 3 * DRM_HZ); } + mtx_unlock(&dev->irq_lock); - if (ret != EINTR) { + if (ret != EINTR && ret != ERESTART) { struct timeval now; microtime(&now); vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; vblwait->reply.sequence = drm_vblank_count(dev, crtc); - DRM_DEBUG("returning %d to client\n", - vblwait->reply.sequence); + DRM_DEBUG("returning %d to client, irq_enabled %d\n", + vblwait->reply.sequence, dev->irq_enabled); } else { DRM_DEBUG("vblank wait interrupted by signal\n"); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906231559.n5NFxA44081861>