drm/i915: implement interruptible sleeps in the overlay code

At least for the common case of userspace ioctls. When doing a
modeset operation, the wait is still uninterruptible. But considering
that failing to turn off the overlay when switching off the crtc it's
running on hangs the chip, it doesn't complicate matters _very_
much. There's just an unkillable X in addition to a black screen.
BUG() about it and explain in the code.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6f818fa..7d3309b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1784,11 +1784,26 @@
 static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
 	struct intel_overlay *overlay;
+	int ret;
 
 	if (!enable && intel_crtc->overlay) {
 		overlay = intel_crtc->overlay;
 		mutex_lock(&overlay->dev->struct_mutex);
-		intel_overlay_switch_off(overlay);
+		for (;;) {
+			ret = intel_overlay_switch_off(overlay);
+			if (ret == 0)
+				break;
+
+			ret = intel_overlay_recover_from_interrupt(overlay, 0);
+			if (ret != 0) {
+				/* overlay doesn't react anymore. Usually
+				 * results in a black screen and an unkillable
+				 * X server. */
+				BUG();
+				overlay->hw_wedged = HW_WEDGED;
+				break;
+			}
+		}
 		mutex_unlock(&overlay->dev->struct_mutex);
 	}
 	/* Let userspace switch the overlay on again. In most cases userspace