[Intel-gfx] [PATCH] set vblank enabled flag correctly across IRQ install/uninstall

Jesse Barnes jbarnes at virtuousgeek.org
Tue Jan 6 19:21:24 CET 2009


In the absence of kernel mode setting, many drivers disable IRQs across VT
switch.  The core DRM vblank code is missing a check for this case however;
even after IRQ disable, the vblank code will still have the vblank_enabled
flag set, so unless we track the fact that they're disabled at IRQ uninstall
time, when we VT switch back in we won't actually re-enable them, which means
any apps waiting on vblank before the switch will hang.

This patch does that and also adds a sanity check to the wait condition to
look for the irq_enabled flag in general, as well as adding a wakeup to the
IRQ uninstall path.

This patch fixes fdo bug #18879, so hopefully we can apply it or another
fix for this problem soon.

-- 
Jesse Barnes, Intel Open Source Technology Center


diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 1e787f8..e2f5d23 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -259,7 +259,8 @@ EXPORT_SYMBOL(drm_irq_install);
  */
 int drm_irq_uninstall(struct drm_device * dev)
 {
-	int irq_enabled;
+	unsigned long irqflags;
+	int irq_enabled, i;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
@@ -269,6 +270,16 @@ int drm_irq_uninstall(struct drm_device * dev)
 	dev->irq_enabled = 0;
 	mutex_unlock(&dev->struct_mutex);
 
+	/*
+	 * Wake up any waiters so they don't hang.
+	 */
+	spin_lock_irqsave(&dev->vbl_lock, irqflags);
+	for (i = 0; i < dev->num_crtcs; i++) {
+		DRM_WAKEUP(&dev->vbl_queue[i]);
+		dev->vblank_enabled[i] = 0;
+	}
+	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
 	if (!irq_enabled)
 		return -EINVAL;
 
@@ -617,8 +628,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
 		DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
 			  vblwait->request.sequence, crtc);
 		DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
-			    ((drm_vblank_count(dev, crtc)
-			      - vblwait->request.sequence) <= (1 << 23)));
+			    (((drm_vblank_count(dev, crtc) -
+			       vblwait->request.sequence) <= (1 << 23)) ||
+			     !dev->irq_enabled));
 
 		if (ret != -EINTR) {
 			struct timeval now;




More information about the Intel-gfx mailing list