diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-02-19 09:48:22 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2009-02-24 23:45:50 -0500 |
commit | b3f5e7329df1a508ac58ebe7509fb7a47b9eab6a (patch) | |
tree | 26053313cadc6914662e88de0af2e2fe04d80913 | |
parent | 7bec756c74b1a5079d5074144bb77a6b3e7d7783 (diff) |
drm: Correct unbalanced drm_vblank_put() during mode setting.
The first time we install a mode, the vblank will be disabled for a pipe
and so drm_vblank_get() in drm_vblank_pre_modeset() will fail. As we
unconditionally call drm_vblank_put() afterwards, the vblank reference
counter becomes unbalanced.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50c..93e677a481f5 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
435 | */ | 435 | */ |
436 | void drm_vblank_put(struct drm_device *dev, int crtc) | 436 | void drm_vblank_put(struct drm_device *dev, int crtc) |
437 | { | 437 | { |
438 | BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); | ||
439 | |||
438 | /* Last user schedules interrupt disable */ | 440 | /* Last user schedules interrupt disable */ |
439 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) | 441 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) |
440 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); | 442 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); |
@@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
460 | * so that interrupts remain enabled in the interim. | 462 | * so that interrupts remain enabled in the interim. |
461 | */ | 463 | */ |
462 | if (!dev->vblank_inmodeset[crtc]) { | 464 | if (!dev->vblank_inmodeset[crtc]) { |
463 | dev->vblank_inmodeset[crtc] = 1; | 465 | dev->vblank_inmodeset[crtc] = 0x1; |
464 | drm_vblank_get(dev, crtc); | 466 | if (drm_vblank_get(dev, crtc) == 0) |
467 | dev->vblank_inmodeset[crtc] |= 0x2; | ||
465 | } | 468 | } |
466 | } | 469 | } |
467 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
@@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
473 | if (dev->vblank_inmodeset[crtc]) { | 476 | if (dev->vblank_inmodeset[crtc]) { |
474 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 477 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
475 | dev->vblank_disable_allowed = 1; | 478 | dev->vblank_disable_allowed = 1; |
476 | dev->vblank_inmodeset[crtc] = 0; | ||
477 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 479 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
478 | drm_vblank_put(dev, crtc); | 480 | |
481 | if (dev->vblank_inmodeset[crtc] & 0x2) | ||
482 | drm_vblank_put(dev, crtc); | ||
483 | |||
484 | dev->vblank_inmodeset[crtc] = 0; | ||
479 | } | 485 | } |
480 | } | 486 | } |
481 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 487 | EXPORT_SYMBOL(drm_vblank_post_modeset); |