aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-02-18 12:08:49 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-19 19:33:43 -0500
commit96a02917a0131e52efefde49c2784c0421d6c439 (patch)
tree92232f7bfdf0db5796b4923722771d9d98074fe2 /drivers/gpu/drm
parent4878cae22a2405b6d33318e2dc99a9c1367fee44 (diff)
drm/i915: Finish page flips and update primary planes after a GPU reset
GPU reset will drop all flips that are still in the ring. So after the reset, call update_plane() for all CRTCs to make sure the primary planes are scanning out from the correct buffer. Also finish all pending flips. That means user space will get its page flip events and won't get stuck waiting for them. v2: Explicitly finish page flips instead of relying on FLIP_DONE interrupt being generated by the base address update. v3: Make two loops over crtcs to avoid deadlocks with the crtc mutex Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> [danvet: Fixup long line complaint from checkpatch.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c38
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
3 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2cd97d1cc920..9fde49a29999 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -915,6 +915,8 @@ static void i915_error_work_func(struct work_struct *work)
915 for_each_ring(ring, dev_priv, i) 915 for_each_ring(ring, dev_priv, i)
916 wake_up_all(&ring->irq_queue); 916 wake_up_all(&ring->irq_queue);
917 917
918 intel_display_handle_reset(dev);
919
918 wake_up_all(&dev_priv->gpu_error.reset_queue); 920 wake_up_all(&dev_priv->gpu_error.reset_queue);
919 } 921 }
920} 922}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 85bf178bac75..ba8307dc03be 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2218,6 +2218,44 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
2218 return dev_priv->display.update_plane(crtc, fb, x, y); 2218 return dev_priv->display.update_plane(crtc, fb, x, y);
2219} 2219}
2220 2220
2221void intel_display_handle_reset(struct drm_device *dev)
2222{
2223 struct drm_i915_private *dev_priv = dev->dev_private;
2224 struct drm_crtc *crtc;
2225
2226 /*
2227 * Flips in the rings have been nuked by the reset,
2228 * so complete all pending flips so that user space
2229 * will get its events and not get stuck.
2230 *
2231 * Also update the base address of all primary
2232 * planes to the the last fb to make sure we're
2233 * showing the correct fb after a reset.
2234 *
2235 * Need to make two loops over the crtcs so that we
2236 * don't try to grab a crtc mutex before the
2237 * pending_flip_queue really got woken up.
2238 */
2239
2240 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
2241 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2242 enum plane plane = intel_crtc->plane;
2243
2244 intel_prepare_page_flip(dev, plane);
2245 intel_finish_page_flip_plane(dev, plane);
2246 }
2247
2248 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
2249 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2250
2251 mutex_lock(&crtc->mutex);
2252 if (intel_crtc->active)
2253 dev_priv->display.update_plane(crtc, crtc->fb,
2254 crtc->x, crtc->y);
2255 mutex_unlock(&crtc->mutex);
2256 }
2257}
2258
2221static int 2259static int
2222intel_finish_fb(struct drm_framebuffer *old_fb) 2260intel_finish_fb(struct drm_framebuffer *old_fb)
2223{ 2261{
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 005a91f1f8f5..febed9a010da 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -695,4 +695,6 @@ extern bool
695intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); 695intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
696extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); 696extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
697 697
698extern void intel_display_handle_reset(struct drm_device *dev);
699
698#endif /* __INTEL_DRV_H__ */ 700#endif /* __INTEL_DRV_H__ */