[PATCH v4 1/3] drm: Implement drm_modeset_lock_all_ctx()

Daniel Vetter daniel at ffwll.ch
Tue Dec 1 02:02:36 PST 2015


On Tue, Dec 01, 2015 at 10:56:59AM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding at nvidia.com>
> 
> This function is like drm_modeset_lock_all(), but it takes the lock
> acquisition context as a parameter rather than storing it in the DRM
> device's mode_config structure.
> 
> Implement drm_modeset_{,un}lock_all() in terms of the new function for
> better code reuse, and add a note to the kerneldoc that new code should
> use the new functions.
> 
> v2: improve kerneldoc
> v4: rename drm_modeset_lock_all_crtcs() to drm_modeset_lock_all_ctx()
>     and take mode_config's .connection_mutex instead of .mutex lock to
>     avoid lock inversion (Daniel Vetter), use drm_modeset_drop_locks()
>     which is now the equivalent of drm_modeset_unlock_all_ctx()
> 
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
>  drivers/gpu/drm/drm_atomic.c       |  3 +-
>  drivers/gpu/drm/drm_modeset_lock.c | 82 ++++++++++++++++++++++++--------------
>  include/drm/drm_modeset_lock.h     |  4 +-
>  3 files changed, 56 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 55b4debad79b..4cbe7c07231c 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,8 +1192,7 @@ retry:
>  			       state->acquire_ctx);

You forgot to remove the connection_mutex right above here
>  	if (ret)
>  		goto retry;
> -	ret = drm_modeset_lock_all_crtcs(state->dev,
> -					 state->acquire_ctx);
> +	ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
>  	if (ret)
>  		goto retry;
>  }
> diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
> index 6675b1428410..341158c92027 100644
> --- a/drivers/gpu/drm/drm_modeset_lock.c
> +++ b/drivers/gpu/drm/drm_modeset_lock.c
> @@ -57,11 +57,18 @@
>  
>  /**
>   * drm_modeset_lock_all - take all modeset locks
> - * @dev: drm device
> + * @dev: DRM device
>   *
>   * This function takes all modeset locks, suitable where a more fine-grained
> - * scheme isn't (yet) implemented. Locks must be dropped with
> - * drm_modeset_unlock_all.
> + * scheme isn't (yet) implemented. Locks must be dropped by calling the
> + * drm_modeset_unlock_all() function.
> + *
> + * This function is deprecated. It allocates a lock acquisition context and
> + * stores it in the DRM device's ->mode_config. This facilitate conversion of
> + * existing code because it removes the need to manually deal with the
> + * acquisition context, but it is also brittle because the context is global
> + * and care must be taken not to nest calls. New code should use the
> + * drm_modeset_lock_all_ctx() function and pass in the context explicitly.
>   */
>  void drm_modeset_lock_all(struct drm_device *dev)
>  {
> @@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
>  	drm_modeset_acquire_init(ctx, 0);
>  
>  retry:
> -	ret = drm_modeset_lock(&config->connection_mutex, ctx);
> -	if (ret)
> -		goto fail;
> -	ret = drm_modeset_lock_all_crtcs(dev, ctx);
> -	if (ret)
> -		goto fail;
> +	ret = drm_modeset_lock_all_ctx(dev, ctx);
> +	if (ret < 0) {
> +		if (ret == -EDEADLK) {
> +			drm_modeset_backoff(ctx);
> +			goto retry;
> +		}
> +
> +		drm_modeset_acquire_fini(ctx);
> +		kfree(ctx);
> +		return;
> +	}
>  
>  	WARN_ON(config->acquire_ctx);
>  
> -	/* now we hold the locks, so now that it is safe, stash the
> -	 * ctx for drm_modeset_unlock_all():
> +	/*
> +	 * We hold the locks now, so it is safe to stash the acquisition
> +	 * context for drm_modeset_unlock_all().
>  	 */
>  	config->acquire_ctx = ctx;
>  
>  	drm_warn_on_modeset_not_all_locked(dev);
> -
> -	return;
> -
> -fail:
> -	if (ret == -EDEADLK) {
> -		drm_modeset_backoff(ctx);
> -		goto retry;
> -	}
> -
> -	kfree(ctx);
>  }
>  EXPORT_SYMBOL(drm_modeset_lock_all);
>  
>  /**
>   * drm_modeset_unlock_all - drop all modeset locks
> - * @dev: device
> + * @dev: DRM device
> + *
> + * This function drops all modeset locks taken by a previous call to the
> + * drm_modeset_lock_all() function.
>   *
> - * This function drop all modeset locks taken by drm_modeset_lock_all.
> + * This function is deprecated. It uses the lock acquisition context stored
> + * in the DRM device's ->mode_config. This facilitates conversion of existing
> + * code because it removes the need to manually deal with the acquisition
> + * context, but it is also brittle because the context is global and care must
> + * be taken not to nest calls. New code should pass the acquisition context
> + * directly to the drm_modeset_drop_locks() function.
>   */
>  void drm_modeset_unlock_all(struct drm_device *dev)
>  {
> @@ -431,14 +442,27 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
>  }
>  EXPORT_SYMBOL(drm_modeset_unlock);
>  
> -/* In some legacy codepaths it's convenient to just grab all the crtc and plane
> - * related locks. */
> -int drm_modeset_lock_all_crtcs(struct drm_device *dev,
> -		struct drm_modeset_acquire_ctx *ctx)
> +/**
> + * drm_modeset_lock_all_ctx - take all modeset locks
> + * @dev: DRM device
> + * @ctx: lock acquisition context
> + *
> + * This function takes all modeset locks, suitable where a more fine-grained
> + * scheme isn't (yet) implemented. Locks must be dropped by calling the
> + * drm_modeset_drop_locks() function.

Imo this needs a bit more explanation.

Note that compared to drm_modeset_lock_all() it does not take
dev->mode_config.mutex, since that lock isn't required for modeset state
changes. Callers which need to grab that lock too need to do so
themselves, outside of the acquire context @ctx.

Locks acquired with this function should be released with
drm_modeset_drop_locks() called on @ctx.

With the kerneldoc augmented and atomic_legacy_backoff fixed this is:

Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>


> + *
> + * Returns: 0 on success or a negative error-code on failure.
> + */
> +int drm_modeset_lock_all_ctx(struct drm_device *dev,
> +			     struct drm_modeset_acquire_ctx *ctx)
>  {
>  	struct drm_crtc *crtc;
>  	struct drm_plane *plane;
> -	int ret = 0;
> +	int ret;
> +
> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
> +	if (ret)
> +		return ret;
>  
>  	drm_for_each_crtc(crtc, dev) {
>  		ret = drm_modeset_lock(&crtc->mutex, ctx);
> @@ -454,4 +478,4 @@ int drm_modeset_lock_all_crtcs(struct drm_device *dev,
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
> +EXPORT_SYMBOL(drm_modeset_lock_all_ctx);
> diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
> index 94938d89347c..c5576fbcb909 100644
> --- a/include/drm/drm_modeset_lock.h
> +++ b/include/drm/drm_modeset_lock.h
> @@ -138,7 +138,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
>  struct drm_modeset_acquire_ctx *
>  drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
>  
> -int drm_modeset_lock_all_crtcs(struct drm_device *dev,
> -		struct drm_modeset_acquire_ctx *ctx);
> +int drm_modeset_lock_all_ctx(struct drm_device *dev,
> +			     struct drm_modeset_acquire_ctx *ctx);
>  
>  #endif /* DRM_MODESET_LOCK_H_ */
> -- 
> 2.5.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list