drm/i915: Decouple the stuck pageflip on modeset
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 5 Sep 2014 06:13:25 +0000 (07:13 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 5 Sep 2014 07:31:24 +0000 (09:31 +0200)
If we successfully confuse the hardware, and cause it to drop a queued
pageflip, we wait for 60s and issue a warning before continuing on with
the modeset. However, this leaves the pending pageflip still stuck
indefinitely. Pretend to userspace that it does complete, and let us
start afresh following the modeset.

v2: Rebase after refactor
v3: Rebase, rebase.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=82612
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_display.c

index 7988f1f22068dead701952396a97c6887465acbe..b912107a139249a98439941311518f24d167f9fa 100644 (file)
@@ -3417,9 +3417,19 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
-       WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
-                                  !intel_crtc_has_pending_flip(crtc),
-                                  60*HZ) == 0);
+       if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
+                                      !intel_crtc_has_pending_flip(crtc),
+                                      60*HZ) == 0)) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               unsigned long flags;
+
+               spin_lock_irqsave(&dev->event_lock, flags);
+               if (intel_crtc->unpin_work) {
+                       WARN_ONCE(1, "Removing stuck page flip\n");
+                       page_flip_completed(intel_crtc);
+               }
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+       }
 
        if (crtc->primary->fb) {
                mutex_lock(&dev->struct_mutex);