Commit 4cba6850 authored by Daniel Vetter's avatar Daniel Vetter

drm/atomic-helper: Reject legacy flips on a disabled pipe

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: default avatarDaniel Stone <daniels@collabora.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1449564561-3896-4-git-send-email-daniel.vetter@ffwll.ch
parent 4cd9fa52
...@@ -508,6 +508,22 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc, ...@@ -508,6 +508,22 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
return -EINVAL; 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; return 0;
} }
......
...@@ -2284,6 +2284,15 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, ...@@ -2284,6 +2284,15 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
goto fail; goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb); 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); ret = drm_atomic_async_commit(state);
if (ret != 0) if (ret != 0)
goto fail; goto fail;
......
...@@ -551,7 +551,8 @@ struct drm_crtc_funcs { ...@@ -551,7 +551,8 @@ struct drm_crtc_funcs {
* ->page_flip() operation is already pending the callback should return * ->page_flip() operation is already pending the callback should return
* -EBUSY. Pageflips on a disabled CRTC (either by setting a NULL mode * -EBUSY. Pageflips on a disabled CRTC (either by setting a NULL mode
* or just runtime disabled through DPMS respectively the new atomic * or just runtime disabled through DPMS respectively the new atomic
* "ACTIVE" state) should result in an -EINVAL error code. * "ACTIVE" state) should result in an -EINVAL error code. Note that
* drm_atomic_helper_page_flip() checks this already for atomic drivers.
*/ */
int (*page_flip)(struct drm_crtc *crtc, int (*page_flip)(struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment