[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