svn commit: r194728 - in stable/7/sys: . contrib/pf dev/drm

Robert Noland rnoland at FreeBSD.org
Tue Jun 23 15:59:12 UTC 2009


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");
 		}


More information about the svn-src-all mailing list