diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2013-02-22 09:53:38 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-03-03 13:51:33 -0500 |
commit | 4a35f83b2b7c6aae3fc0d1c4554fdc99dc33ad07 (patch) | |
tree | 82bd8df4e7b0719c38ca722b358d6e83922bd607 /drivers/gpu | |
parent | b18ac466956c7e7b5abf7a2d6adf8c626267d0ae (diff) |
drm/i915: Don't clobber crtc->fb when queue_flip fails
Restore crtc->fb to the old framebuffer if queue_flip fails.
While at it, kill the pointless intel_fb temp variable.
v2: Update crtc->fb before queue_flip and restore it back
after a failure.
Cc: stable@vger.kernel.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reported-and-Tested-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0ff10b3af9ea..09659ff6d24d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -7264,8 +7264,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7264 | { | 7264 | { |
7265 | struct drm_device *dev = crtc->dev; | 7265 | struct drm_device *dev = crtc->dev; |
7266 | struct drm_i915_private *dev_priv = dev->dev_private; | 7266 | struct drm_i915_private *dev_priv = dev->dev_private; |
7267 | struct intel_framebuffer *intel_fb; | 7267 | struct drm_framebuffer *old_fb = crtc->fb; |
7268 | struct drm_i915_gem_object *obj; | 7268 | struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; |
7269 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 7269 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
7270 | struct intel_unpin_work *work; | 7270 | struct intel_unpin_work *work; |
7271 | unsigned long flags; | 7271 | unsigned long flags; |
@@ -7290,8 +7290,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7290 | 7290 | ||
7291 | work->event = event; | 7291 | work->event = event; |
7292 | work->crtc = crtc; | 7292 | work->crtc = crtc; |
7293 | intel_fb = to_intel_framebuffer(crtc->fb); | 7293 | work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; |
7294 | work->old_fb_obj = intel_fb->obj; | ||
7295 | INIT_WORK(&work->work, intel_unpin_work_fn); | 7294 | INIT_WORK(&work->work, intel_unpin_work_fn); |
7296 | 7295 | ||
7297 | ret = drm_vblank_get(dev, intel_crtc->pipe); | 7296 | ret = drm_vblank_get(dev, intel_crtc->pipe); |
@@ -7311,9 +7310,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7311 | intel_crtc->unpin_work = work; | 7310 | intel_crtc->unpin_work = work; |
7312 | spin_unlock_irqrestore(&dev->event_lock, flags); | 7311 | spin_unlock_irqrestore(&dev->event_lock, flags); |
7313 | 7312 | ||
7314 | intel_fb = to_intel_framebuffer(fb); | ||
7315 | obj = intel_fb->obj; | ||
7316 | |||
7317 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) | 7313 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) |
7318 | flush_workqueue(dev_priv->wq); | 7314 | flush_workqueue(dev_priv->wq); |
7319 | 7315 | ||
@@ -7348,6 +7344,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7348 | 7344 | ||
7349 | cleanup_pending: | 7345 | cleanup_pending: |
7350 | atomic_dec(&intel_crtc->unpin_work_count); | 7346 | atomic_dec(&intel_crtc->unpin_work_count); |
7347 | crtc->fb = old_fb; | ||
7351 | drm_gem_object_unreference(&work->old_fb_obj->base); | 7348 | drm_gem_object_unreference(&work->old_fb_obj->base); |
7352 | drm_gem_object_unreference(&obj->base); | 7349 | drm_gem_object_unreference(&obj->base); |
7353 | mutex_unlock(&dev->struct_mutex); | 7350 | mutex_unlock(&dev->struct_mutex); |