[PATCH] drm/atomic: Acquire connection_mutex lock in drm_helper_probe_single_connector_modes, v4.

Boris Brezillon boris.brezillon at free-electrons.com
Mon Apr 10 10:16:40 UTC 2017


Hi Maarteen,

Sorry for the late review, I was on vacation last week.

On Thu,  6 Apr 2017 20:55:20 +0200
Maarten Lankhorst <maarten.lankhorst at linux.intel.com> wrote:

> mode_valid() called from drm_helper_probe_single_connector_modes()
> may need to look at connector->state because what a valid mode is may
> depend on connector properties being set. For example some HDMI modes
> might be rejected when a connector property forces the connector
> into DVI mode.
> 
> Some implementations of detect() already lock all state,
> so we have to pass an acquire_ctx to them to prevent a deadlock.
> 
> This means changing the function signature of detect() slightly,
> and passing the acquire_ctx for locking multiple crtc's.
> For the callbacks, it will always be non-zero. To allow callers
> not to worry about this, drm_helper_probe_detect_ctx is added
> which might handle -EDEADLK for you.
> 
> Changes since v1:
> - Always set ctx parameter.
> Changes since v2:
> - Always take connection_mutex when probing.
> Changes since v3:
> - Remove the ctx from intel_dp_long_pulse, and add
>   WARN_ON(!connection_mutex) (danvet)
> - Update docs to clarify the locking situation. (danvet)

Maybe this is something DRM-specific, but usually we put the changelog
after the '---' to avoid having it in the final commit.

Same goes for the ", v4" suffix in the commit title, it should be
'[PATCH vX] <commit description>'.

> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Boris Brezillon <boris.brezillon at free-electrons.com>
> Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
>  drivers/gpu/drm/drm_probe_helper.c       | 100 ++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_crt.c         |  25 ++++----
>  drivers/gpu/drm/i915/intel_display.c     |  25 ++++----
>  drivers/gpu/drm/i915/intel_dp.c          |  21 +++----
>  drivers/gpu/drm/i915/intel_drv.h         |   8 +--
>  drivers/gpu/drm/i915/intel_hotplug.c     |   3 +-
>  drivers/gpu/drm/i915/intel_tv.c          |  21 +++----
>  include/drm/drm_connector.h              |   6 ++
>  include/drm/drm_crtc_helper.h            |   3 +
>  include/drm/drm_modeset_helper_vtables.h |  36 +++++++++++
>  10 files changed, 187 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index efb5e5e8ce62..1b0c14ab3fff 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -169,12 +169,73 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
>  EXPORT_SYMBOL(drm_kms_helper_poll_enable);
>  
>  static enum drm_connector_status
> -drm_connector_detect(struct drm_connector *connector, bool force)
> +drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)

The function name is misleading IMHO. AFAIU, this helper is
instantiating a new context because the caller did not provide one, so
how about renaming it drm_helper_probe_detect_no_ctx()?

>  {
> -	return connector->funcs->detect ?
> -		connector->funcs->detect(connector, force) :
> -		connector_status_connected;
> +	const struct drm_connector_helper_funcs *funcs = connector->helper_private;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret;
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +retry:
> +	ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx);
> +	if (!ret) {
> +		if (funcs->detect_ctx)
> +			ret = funcs->detect_ctx(connector, &ctx, force);
> +		else if (connector->funcs->detect)
> +			ret = connector->funcs->detect(connector, force);
> +		else
> +			ret = connector_status_connected;
> +	}
> +
> +	if (ret == -EDEADLK) {
> +		drm_modeset_backoff(&ctx);
> +		goto retry;
> +	}
> +
> +	if (WARN_ON(ret < 0))
> +		ret = connector_status_unknown;
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret;
> +}

[...]

>  	/**
> +	 * @detect_ctx:
> +	 *
> +	 * Check to see if anything is attached to the connector. The parameter
> +	 * force is set to false whilst polling, true when checking the
> +	 * connector due to a user request. force can be used by the driver to
> +	 * avoid expensive, destructive operations during automated probing.
> +	 *
> +	 * This callback is optional, if not implemented the connector will be
> +	 * considered as always being attached.
> +	 *
> +	 * This is the atomic version of &drm_connector_funcs.detect.
> +	 *
> +	 * To avoid races against concurrent connector state updates, the
> +	 * helper libraries always call this with ctx set to a valid context,
> +	 * and &drm_mode_config.connection_mutex will always be locked with
> +	 * the ctx parameter set to this ctx. This allows taking additional
> +	 * locks as required.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * &drm_connector_status indicating the connector's status,
> +	 * or the error code returned by drm_modeset_lock(), -EDEADLK.
> +	 */
> +	int (*detect_ctx)(struct drm_connector *connector,
> +			  struct drm_modeset_acquire_ctx *ctx,
> +			  bool force);

AFAIU (correct me if I'm wrong), those who don't care about the ctx
because they don't need to take extra locks can just ignore it. If this
is the case, I wonder if we shouldn't patch all drivers to use the new
prototype instead of adding a new method (which adds to the DRM API
complexity, even if it's well documented ;-)).

Anyway, this is just my opinion, and Daniel was okay with that, so
don't bother changing that right now.

Regards,

Boris


More information about the dri-devel mailing list