From: Ville Syrj?l? <ville.syrjala at linux.intel.com> If the GPU hangs, release all pending atomic flips from the queue. Signed-off-by: Ville Syrj?l? <ville.syrjala at linux.intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/intel_atomic.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 31 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2f0dce2..47d6067 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1486,6 +1486,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged) */ for_each_ring(ring, dev_priv, i) wake_up_all(&ring->irq_queue); + intel_atomic_wedged(dev); } queue_work(dev_priv->wq, &dev_priv->error_work); diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 2ebceec..f59be7f 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -2232,6 +2232,30 @@ void intel_atomic_notify_ring(struct drm_device *dev, spin_unlock_irqrestore(&dev_priv->flip.lock, flags); } +void intel_atomic_wedged(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_flip *intel_flip; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->flip.lock, flags); + + list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) { + struct intel_ring_buffer *ring = intel_flip->ring; + + if (ring) { + intel_flip->ring = NULL; + ring->irq_put(ring); + } + } + + /* all flips are "ready" so no need to check with intel_atomic_flips_ready() */ + if (!list_empty(&dev_priv->flip.list)) + queue_work(dev_priv->flip.wq, &dev_priv->flip.work); + + spin_unlock_irqrestore(&dev_priv->flip.lock, flags); +} + static void atomic_pipe_commit(struct drm_device *dev, struct intel_atomic_state *state, int pipe) @@ -2409,6 +2433,11 @@ static void atomic_pipe_commit(struct drm_device *dev, if (rings_mask == 0) return; + if (atomic_read(&dev_priv->mm.wedged)) { + intel_atomic_wedged(dev); + return; + } + /* * Double check to catch cases where the irq * fired before the flip was placed onto flip.list. diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 446fa1c..33fac47 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -731,6 +731,7 @@ extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *fi extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe); extern void intel_atomic_clear_flips(struct drm_crtc *crtc); extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring); +extern void intel_atomic_wedged(struct drm_device *dev); extern void intel_enable_primary(struct drm_crtc *crtc); extern void intel_disable_primary(struct drm_crtc *crtc); -- 1.7.8.6