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>

authored by Jesse Barnes and committed by Eric Anholt b1b87f6b ee25df2b

+9 -7
+9 -7
drivers/gpu/drm/i915/intel_display.c
··· 4081 struct intel_unpin_work { 4082 struct work_struct work; 4083 struct drm_device *dev; 4084 - struct drm_gem_object *obj; 4085 struct drm_pending_vblank_event *event; 4086 int pending; 4087 }; ··· 4093 container_of(__work, struct intel_unpin_work, work); 4094 4095 mutex_lock(&work->dev->struct_mutex); 4096 - i915_gem_object_unpin(work->obj); 4097 - drm_gem_object_unreference(work->obj); 4098 mutex_unlock(&work->dev->struct_mutex); 4099 kfree(work); 4100 } ··· 4118 work = intel_crtc->unpin_work; 4119 if (work == NULL || !work->pending) { 4120 if (work && !work->pending) { 4121 - obj_priv = work->obj->driver_private; 4122 DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n", 4123 obj_priv, 4124 atomic_read(&obj_priv->pending_flip)); ··· 4143 4144 spin_unlock_irqrestore(&dev->event_lock, flags); 4145 4146 - obj_priv = work->obj->driver_private; 4147 4148 /* Initial scanout buffer will have a 0 pending flip count */ 4149 if ((atomic_read(&obj_priv->pending_flip) == 0) || ··· 4192 work->event = event; 4193 work->dev = crtc->dev; 4194 intel_fb = to_intel_framebuffer(crtc->fb); 4195 - work->obj = intel_fb->obj; 4196 INIT_WORK(&work->work, intel_unpin_work_fn); 4197 4198 /* We borrow the event spin lock for protecting unpin_work */ ··· 4221 } 4222 4223 /* Reference the old fb object for the scheduled work. */ 4224 - drm_gem_object_reference(work->obj); 4225 4226 crtc->fb = fb; 4227 i915_gem_object_flush_write_domain(obj); 4228 drm_vblank_get(dev, intel_crtc->pipe); 4229 obj_priv = obj->driver_private; 4230 atomic_inc(&obj_priv->pending_flip); 4231 4232 BEGIN_LP_RING(4); 4233 OUT_RING(MI_DISPLAY_FLIP |
··· 4081 struct intel_unpin_work { 4082 struct work_struct work; 4083 struct drm_device *dev; 4084 + struct drm_gem_object *old_fb_obj; 4085 + struct drm_gem_object *pending_flip_obj; 4086 struct drm_pending_vblank_event *event; 4087 int pending; 4088 }; ··· 4092 container_of(__work, struct intel_unpin_work, work); 4093 4094 mutex_lock(&work->dev->struct_mutex); 4095 + i915_gem_object_unpin(work->old_fb_obj); 4096 + drm_gem_object_unreference(work->old_fb_obj); 4097 mutex_unlock(&work->dev->struct_mutex); 4098 kfree(work); 4099 } ··· 4117 work = intel_crtc->unpin_work; 4118 if (work == NULL || !work->pending) { 4119 if (work && !work->pending) { 4120 + obj_priv = work->pending_flip_obj->driver_private; 4121 DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n", 4122 obj_priv, 4123 atomic_read(&obj_priv->pending_flip)); ··· 4142 4143 spin_unlock_irqrestore(&dev->event_lock, flags); 4144 4145 + obj_priv = work->pending_flip_obj->driver_private; 4146 4147 /* Initial scanout buffer will have a 0 pending flip count */ 4148 if ((atomic_read(&obj_priv->pending_flip) == 0) || ··· 4191 work->event = event; 4192 work->dev = crtc->dev; 4193 intel_fb = to_intel_framebuffer(crtc->fb); 4194 + work->old_fb_obj = intel_fb->obj; 4195 INIT_WORK(&work->work, intel_unpin_work_fn); 4196 4197 /* We borrow the event spin lock for protecting unpin_work */ ··· 4220 } 4221 4222 /* Reference the old fb object for the scheduled work. */ 4223 + drm_gem_object_reference(work->old_fb_obj); 4224 4225 crtc->fb = fb; 4226 i915_gem_object_flush_write_domain(obj); 4227 drm_vblank_get(dev, intel_crtc->pipe); 4228 obj_priv = obj->driver_private; 4229 atomic_inc(&obj_priv->pending_flip); 4230 + work->pending_flip_obj = obj; 4231 4232 BEGIN_LP_RING(4); 4233 OUT_RING(MI_DISPLAY_FLIP |