From e6c3a2a6d358a726c2c52cb0132c9ad8f6f37486 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Sep 2010 23:04:43 +0100 Subject: [PATCH] drm/i915: Use an uninterruptible wait for page-flips during modeset We need to drain the pending flips prior to disabling the pipe during modeset, and these need to be done in an uninterruptible fashion. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 3 --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 29 +++++++++++++++++++--------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a5aa11fbb68a..6aa34317dcbf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1023,9 +1023,6 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, bool interruptible, struct intel_ring_buffer *ring); -int i915_gem_wait_for_pending_flip(struct drm_device *dev, - struct drm_gem_object **object_list, - int count); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 174e38abc9ef..dec7bbc81cb6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3506,7 +3506,7 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, return 0; } -int +static int i915_gem_wait_for_pending_flip(struct drm_device *dev, struct drm_gem_object **object_list, int count) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dda0f646bda3..6fbaa633d946 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1593,17 +1593,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, } if (old_fb) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj; struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - if (atomic_read(&obj_priv->pending_flip)) { - ret = i915_gem_wait_for_pending_flip(dev, &obj, 1); - if (ret) { - i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - } + wait_event(dev_priv->pending_flip_queue, + atomic_read(&obj_priv->pending_flip) == 0); } ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); @@ -1954,6 +1949,20 @@ static void intel_clear_scanline_wait(struct drm_device *dev) } } +static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) +{ + struct drm_i915_gem_object *obj_priv; + struct drm_i915_private *dev_priv; + + if (crtc->fb == NULL) + return; + + obj_priv = to_intel_bo(to_intel_framebuffer(crtc->fb)->obj); + dev_priv = crtc->dev->dev_private; + wait_event(dev_priv->pending_flip_queue, + atomic_read(&obj_priv->pending_flip) == 0); +} + static void ironlake_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2130,6 +2139,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) if (!intel_crtc->active) return; + intel_crtc_wait_for_pending_flips(crtc); drm_vblank_off(dev, pipe); intel_crtc_update_cursor(crtc, false); @@ -2377,9 +2387,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) return; /* Give the overlay scaler a chance to disable if it's on this pipe */ + intel_crtc_wait_for_pending_flips(crtc); + drm_vblank_off(dev, pipe); intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); - drm_vblank_off(dev, pipe); if (dev_priv->cfb_plane == plane && dev_priv->display.disable_fbc) -- 2.34.1