From 4cba68507cf58db99752cf79198beb4a85a9f8ce Mon Sep 17 00:00:00 2001
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Tue, 8 Dec 2015 09:49:20 +0100
Subject: [PATCH] drm/atomic-helper: Reject legacy flips on a disabled pipe
Mime-version: 1.0
Content-type: text/plain; charset=UTF-8
Content-transfer-encoding: 8bit
Git-commit: 4cba68507cf58db99752cf79198beb4a85a9f8ce
Patch-mainline: 4.5-rc1
References: bsc#991038

We want this for consistency with existing page_flip semantics.

Since this spurred quite a discussion on IRC also document why we
reject event generation when the pipe is off: It's not that it's hard
to implement, but userspace has a track recording which proves that it's
way too easy to accidentally abuse and cause havoc. We want to make
sure userspace doesn't get away with that.

V2: Somehow thought we do reject events already, but that code only
existed in my imagination ... Also suggestions from Thierry.

Cc: Daniel Stone <daniels@collabora.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1449564561-3896-4-git-send-email-daniel.vetter@ffwll.ch
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/drm_atomic.c        |   16 ++++++++++++++++
 drivers/gpu/drm/drm_atomic_helper.c |    9 +++++++++
 2 files changed, 25 insertions(+)

--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -502,6 +502,22 @@ static int drm_atomic_crtc_check(struct
 		return -EINVAL;
 	}
 
+	/*
+	 * Reject event generation for when a CRTC is off and stays off.
+	 * It wouldn't be hard to implement this, but userspace has a track
+	 * record of happily burning through 100% cpu (or worse, crash) when the
+	 * display pipe is suspended. To avoid all that fun just reject updates
+	 * that ask for events since likely that indicates a bug in the
+	 * compositor's drawing loop. This is consistent with the vblank IOCTL
+	 * and legacy page_flip IOCTL which also reject service on a disabled
+	 * pipe.
+	 */
+	if (state->event && !state->active && !crtc->state->active) {
+		DRM_DEBUG_ATOMIC("[CRTC:%d] requesting event but off\n",
+				 crtc->base.id);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2234,6 +2234,15 @@ retry:
 		goto fail;
 	drm_atomic_set_fb_for_plane(plane_state, fb);
 
+	/* Make sure we don't accidentally do a full modeset. */
+	state->allow_modeset = false;
+	if (!crtc_state->active) {
+		DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
+				 crtc->base.id);
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	ret = drm_atomic_async_commit(state);
 	if (ret != 0)
 		goto fail;
