[PATCH 1/2] drm/atomic: track bitmask of planes attached to crtc
Daniel Vetter
daniel at ffwll.ch
Tue Nov 25 06:15:51 PST 2014
On Fri, Nov 21, 2014 at 03:28:31PM -0500, Rob Clark wrote:
> Chasing plane->state->crtc of planes that are *not* part of the same
> atomic update is racy, making it incredibly awkward (or impossible) to
> do something simple like iterate over all planes and figure out which
> ones are attached to a crtc.
>
> Solve this by adding a bitmask of currently attached planes in the
> crtc-state.
>
> Note that the transitional helpers do not maintain the plane_mask. But
> they only support the legacy ioctls, which have sufficient brute-force
> locking around plane updates that they can continue to loop over all
> planes to see what is attached to a crtc the old way.
>
> Signed-off-by: Rob Clark <robdclark at gmail.com>
> ---
> drivers/gpu/drm/drm_atomic.c | 25 ++++++++++++++++++++-----
> drivers/gpu/drm/drm_atomic_helper.c | 8 ++++----
> include/drm/drm_atomic.h | 4 ++--
> include/drm/drm_crtc.h | 14 +++++++++++---
> 4 files changed, 37 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index d3b4674..8effbba 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -350,7 +350,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
>
> /**
> * drm_atomic_set_crtc_for_plane - set crtc for plane
> - * @plane_state: atomic state object for the plane
> + * @state: the incoming atomic state
> + * @plane: the plane whose incoming state to update
> * @crtc: crtc to use for the plane
> *
> * Changing the assigned crtc for a plane requires us to grab the lock and state
> @@ -363,20 +364,34 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
> * sequence must be restarted. All other errors are fatal.
> */
> int
> -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> - struct drm_crtc *crtc)
> +drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
> + struct drm_plane *plane, struct drm_crtc *crtc)
> {
> + struct drm_plane_state *plane_state =
> + drm_atomic_get_plane_state(state, plane);
> struct drm_crtc_state *crtc_state;
>
> - if (crtc) {
> + /* acquire outgoing crtc lock, and clear bit in outgoing crtc mask: */
Ok still don't like these comments since at least for the old crtc it's
wrong: We already must both hold the lock and copied the state. So I've
dropped them (kerneldoc already mentions this too).
> + if (plane_state->crtc) {
> crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> - crtc);
> + plane_state->crtc);
> if (IS_ERR(crtc_state))
And changed this to WARN_ON too to make sure this never fails. The pulled
it into my atomic-fixes branch.
-Daniel
> return PTR_ERR(crtc_state);
> +
> + crtc_state->plane_mask &= ~(1 << drm_plane_index(plane));
> }
>
> plane_state->crtc = crtc;
>
> + /* acquire incoming crtc lock, and set bit in incoming crtc mask: */
> + if (crtc) {
> + crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> + crtc);
> + if (IS_ERR(crtc_state))
> + return PTR_ERR(crtc_state);
> + crtc_state->plane_mask |= (1 << drm_plane_index(plane));
> + }
> +
> if (crtc)
> DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
> plane_state, crtc->base.id);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index a17b8e9..d765d37 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1187,7 +1187,7 @@ retry:
> goto fail;
> }
>
> - ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
> + ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
> if (ret != 0)
> goto fail;
> drm_atomic_set_fb_for_plane(plane_state, fb);
> @@ -1255,7 +1255,7 @@ retry:
> goto fail;
> }
>
> - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
> + ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
> if (ret != 0)
> goto fail;
> drm_atomic_set_fb_for_plane(plane_state, NULL);
> @@ -1426,7 +1426,7 @@ retry:
> goto fail;
> }
>
> - ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
> + ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
> if (ret != 0)
> goto fail;
> drm_atomic_set_fb_for_plane(primary_state, set->fb);
> @@ -1698,7 +1698,7 @@ retry:
> goto fail;
> }
>
> - ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
> + ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
> if (ret != 0)
> goto fail;
> drm_atomic_set_fb_for_plane(plane_state, fb);
> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> index 9d91916..6ff8775 100644
> --- a/include/drm/drm_atomic.h
> +++ b/include/drm/drm_atomic.h
> @@ -44,8 +44,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
> struct drm_connector *connector);
>
> int __must_check
> -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> - struct drm_crtc *crtc);
> +drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
> + struct drm_plane *plane, struct drm_crtc *crtc);
> void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> struct drm_framebuffer *fb);
> int __must_check
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index b459e8f..4cf6905 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -231,6 +231,7 @@ struct drm_atomic_state;
> * struct drm_crtc_state - mutable CRTC state
> * @enable: whether the CRTC should be enabled, gates all other state
> * @mode_changed: for use by helpers and drivers when computing state updates
> + * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
> * @last_vblank_count: for helpers and drivers to capture the vblank of the
> * update to ensure framebuffer cleanup isn't done too early
> * @planes_changed: for use by helpers and drivers when computing state updates
> @@ -247,6 +248,13 @@ struct drm_crtc_state {
> bool planes_changed : 1;
> bool mode_changed : 1;
>
> + /* attached planes bitmask:
> + * WARNING: transitional helpers do not maintain plane_mask so
> + * drivers not converted over to atomic helpers should not rely
> + * on plane_mask being accurate!
> + */
> + u32 plane_mask;
> +
> /* last_vblank_count: for vblank waits before cleanup */
> u32 last_vblank_count;
>
> @@ -438,7 +446,7 @@ struct drm_crtc {
> * @state: backpointer to global drm_atomic_state
> */
> struct drm_connector_state {
> - struct drm_crtc *crtc;
> + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
>
> struct drm_encoder *best_encoder;
>
> @@ -673,8 +681,8 @@ struct drm_connector {
> * @state: backpointer to global drm_atomic_state
> */
> struct drm_plane_state {
> - struct drm_crtc *crtc;
> - struct drm_framebuffer *fb;
> + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
> + struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
> struct fence *fence;
>
> /* Signed dest location allows it to be partially off screen */
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
More information about the dri-devel
mailing list