From: Ville Syrjälä <ville.syrj...@linux.intel.com>

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.

The base address update will also generate a FLIP_DONE interrupt, which
will complete any pending flips. That means user space will get its
page flip events and won't get stuck waiting for them.

Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c      |  2 ++
 drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 672816a..873552d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -917,6 +917,8 @@ static void i915_error_work_func(struct work_struct *work)
 
                wake_up_all(&dev_priv->pending_flip_queue);
 
+               intel_display_handle_reset(dev);
+
                wake_up_all(&dev_priv->gpu_error.reset_queue);
        }
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index f0c6416..9838da1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2218,6 +2218,32 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct 
drm_framebuffer *fb,
        return dev_priv->display.update_plane(crtc, fb, x, y);
 }
 
+void intel_display_handle_reset(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+
+       /*
+        * Flips in the rings have been nuked by the reset,
+        * so just update the base address of all primary
+        * planes to the the last fb to make sure we're
+        * showing the correct fb after a reset.
+        *
+        * As a nice side effect this also generates a FLIP_DONE
+        * interrupt which will complete pending page flips, and
+        * thus user space will get its events and not get stuck.
+        */
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               mutex_lock(&crtc->mutex);
+
+               if (to_intel_crtc(crtc)->active)
+                       dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, 
crtc->y);
+
+               mutex_unlock(&crtc->mutex);
+       }
+}
+
 static int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d282052..0dc14c2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -694,4 +694,6 @@ extern bool
 intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
+extern void intel_display_handle_reset(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.12.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to