Skip to content

Commit

Permalink
drm/i915: Use an uninterruptible wait for page-flips during modeset
Browse files Browse the repository at this point in the history
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 <chris@chris-wilson.co.uk>
  • Loading branch information
Chris Wilson committed Sep 24, 2010
1 parent d3849ed commit e6c3a2a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 13 deletions.
3 changes: 0 additions & 3 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
29 changes: 20 additions & 9 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit e6c3a2a

Please sign in to comment.