aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-01-26 17:40:05 -0500
committerEric Anholt <eric@anholt.net>2010-02-10 17:33:04 -0500
commitb1b87f6b65a770a69f3632cf7c1f9182547c1249 (patch)
tree6bcd3116e569da55789c94112e9d7afc8042f9be
parentee25df2bc379728c45d81e04cf87984db1425edf (diff)
drm/i915: untangle page flip completion
When a new page flip is requested, we need to both queue an unpin for the current framebuffer, and also increment the flip pending count on the newly submitted buffer. At flip finish time, we need to unpin the old fb and decrement the flip pending count on the new buffer. The old code was conflating the two, and led to hangs when new direct rendered apps were started, replacing the existing frame buffer. This patch splits out the buffers and prevents the hangs. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Kristian Høgsberg <krh@bitplanet.net> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a4d382c8bf58..dc6ffe82d2cd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4081,7 +4081,8 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
4081struct intel_unpin_work { 4081struct intel_unpin_work {
4082 struct work_struct work; 4082 struct work_struct work;
4083 struct drm_device *dev; 4083 struct drm_device *dev;
4084 struct drm_gem_object *obj; 4084 struct drm_gem_object *old_fb_obj;
4085 struct drm_gem_object *pending_flip_obj;
4085 struct drm_pending_vblank_event *event; 4086 struct drm_pending_vblank_event *event;
4086 int pending; 4087 int pending;
4087}; 4088};
@@ -4092,8 +4093,8 @@ static void intel_unpin_work_fn(struct work_struct *__work)
4092 container_of(__work, struct intel_unpin_work, work); 4093 container_of(__work, struct intel_unpin_work, work);
4093 4094
4094 mutex_lock(&work->dev->struct_mutex); 4095 mutex_lock(&work->dev->struct_mutex);
4095 i915_gem_object_unpin(work->obj); 4096 i915_gem_object_unpin(work->old_fb_obj);
4096 drm_gem_object_unreference(work->obj); 4097 drm_gem_object_unreference(work->old_fb_obj);
4097 mutex_unlock(&work->dev->struct_mutex); 4098 mutex_unlock(&work->dev->struct_mutex);
4098 kfree(work); 4099 kfree(work);
4099} 4100}
@@ -4117,7 +4118,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
4117 work = intel_crtc->unpin_work; 4118 work = intel_crtc->unpin_work;
4118 if (work == NULL || !work->pending) { 4119 if (work == NULL || !work->pending) {
4119 if (work && !work->pending) { 4120 if (work && !work->pending) {
4120 obj_priv = work->obj->driver_private; 4121 obj_priv = work->pending_flip_obj->driver_private;
4121 DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n", 4122 DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
4122 obj_priv, 4123 obj_priv,
4123 atomic_read(&obj_priv->pending_flip)); 4124 atomic_read(&obj_priv->pending_flip));
@@ -4142,7 +4143,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
4142 4143
4143 spin_unlock_irqrestore(&dev->event_lock, flags); 4144 spin_unlock_irqrestore(&dev->event_lock, flags);
4144 4145
4145 obj_priv = work->obj->driver_private; 4146 obj_priv = work->pending_flip_obj->driver_private;
4146 4147
4147 /* Initial scanout buffer will have a 0 pending flip count */ 4148 /* Initial scanout buffer will have a 0 pending flip count */
4148 if ((atomic_read(&obj_priv->pending_flip) == 0) || 4149 if ((atomic_read(&obj_priv->pending_flip) == 0) ||
@@ -4191,7 +4192,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4191 work->event = event; 4192 work->event = event;
4192 work->dev = crtc->dev; 4193 work->dev = crtc->dev;
4193 intel_fb = to_intel_framebuffer(crtc->fb); 4194 intel_fb = to_intel_framebuffer(crtc->fb);
4194 work->obj = intel_fb->obj; 4195 work->old_fb_obj = intel_fb->obj;
4195 INIT_WORK(&work->work, intel_unpin_work_fn); 4196 INIT_WORK(&work->work, intel_unpin_work_fn);
4196 4197
4197 /* We borrow the event spin lock for protecting unpin_work */ 4198 /* We borrow the event spin lock for protecting unpin_work */
@@ -4220,13 +4221,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4220 } 4221 }
4221 4222
4222 /* Reference the old fb object for the scheduled work. */ 4223 /* Reference the old fb object for the scheduled work. */
4223 drm_gem_object_reference(work->obj); 4224 drm_gem_object_reference(work->old_fb_obj);
4224 4225
4225 crtc->fb = fb; 4226 crtc->fb = fb;
4226 i915_gem_object_flush_write_domain(obj); 4227 i915_gem_object_flush_write_domain(obj);
4227 drm_vblank_get(dev, intel_crtc->pipe); 4228 drm_vblank_get(dev, intel_crtc->pipe);
4228 obj_priv = obj->driver_private; 4229 obj_priv = obj->driver_private;
4229 atomic_inc(&obj_priv->pending_flip); 4230 atomic_inc(&obj_priv->pending_flip);
4231 work->pending_flip_obj = obj;
4230 4232
4231 BEGIN_LP_RING(4); 4233 BEGIN_LP_RING(4);
4232 OUT_RING(MI_DISPLAY_FLIP | 4234 OUT_RING(MI_DISPLAY_FLIP |