Skip to content

Commit

Permalink
drm/i915: set vblank enabled flag correctly across IRQ install/uninstall
Browse files Browse the repository at this point in the history
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.

Fixes fdo bug #18879 with compiz hangs at VT switch.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
  • Loading branch information
Jesse Barnes authored and Dave Airlie committed Jan 10, 2009
1 parent 71e0ffa commit dc1336f
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,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;
Expand All @@ -277,6 +278,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;

Expand Down Expand Up @@ -652,8 +663,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
vblwait->request.sequence, crtc);
dev->last_vblank_wait[crtc] = vblwait->request.sequence;
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;
Expand Down

0 comments on commit dc1336f

Please sign in to comment.