summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-09-20 15:41:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-09-21 11:24:17 +0100
commit265db9585e570814d2f7aca109c5563bcde9c948 (patch)
tree5319dd865de1d85c9135b8b9227f32db636b9aca /drivers/gpu
parentc78ec30bba52754b9f21a899eac2e2f5a7486116 (diff)
downloadlwn-265db9585e570814d2f7aca109c5563bcde9c948.tar.gz
lwn-265db9585e570814d2f7aca109c5563bcde9c948.zip
drm/i915: Drain any pending flips on the fb prior to unpinning
If we have queued a page flip on the current fb and then request a mode change, wait until the page flip completes before performing the new request. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c41
3 files changed, 26 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 37a44c80efd2..ce8ff8fdc55c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1024,6 +1024,9 @@ 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 58baecc821a5..a8ddcd499b3b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3497,7 +3497,7 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec,
return 0;
}
-static int
+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 791374c888da..461bf4879e0a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1564,11 +1564,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_device *dev = crtc->dev;
struct drm_i915_master_private *master_priv;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_framebuffer *intel_fb;
- struct drm_i915_gem_object *obj_priv;
- struct drm_gem_object *obj;
- int pipe = intel_crtc->pipe;
- int plane = intel_crtc->plane;
int ret;
/* no fb bound */
@@ -1577,38 +1572,46 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return 0;
}
- switch (plane) {
+ switch (intel_crtc->plane) {
case 0:
case 1:
break;
default:
- DRM_ERROR("Can't update plane %d in SAREA\n", plane);
return -EINVAL;
}
- intel_fb = to_intel_framebuffer(crtc->fb);
- obj = intel_fb->obj;
- obj_priv = to_intel_bo(obj);
-
mutex_lock(&dev->struct_mutex);
- ret = intel_pin_and_fence_fb_obj(dev, obj, false);
+ ret = intel_pin_and_fence_fb_obj(dev,
+ to_intel_framebuffer(crtc->fb)->obj,
+ false);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
+ if (old_fb) {
+ 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;
+ }
+ }
+ }
+
ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y);
if (ret) {
- i915_gem_object_unpin(obj);
+ i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
- if (old_fb) {
- intel_fb = to_intel_framebuffer(old_fb);
- obj_priv = to_intel_bo(intel_fb->obj);
- i915_gem_object_unpin(intel_fb->obj);
- }
+ if (old_fb)
+ i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj);
mutex_unlock(&dev->struct_mutex);
@@ -1619,7 +1622,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
if (!master_priv->sarea_priv)
return 0;
- if (pipe) {
+ if (intel_crtc->pipe) {
master_priv->sarea_priv->pipeB_x = x;
master_priv->sarea_priv->pipeB_y = y;
} else {