[Intel-gfx] [PATCH 3/8] drm: Handle properties in the core for atomic drivers

Archit Taneja architt at codeaurora.org
Tue Jul 25 09:36:53 UTC 2017



On 07/25/2017 01:31 PM, Daniel Vetter wrote:
> The reason behind the original indirection through the helper
> functions was to allow existing drivers to overwrite how they handle
> properties. For example when a vendor-specific userspace had
> expectations that didn't match atomic. That seemed likely, since
> atomic is standardizing a _lot_ more of the behaviour of a kms driver.
> 
> But 20 drivers later there's no such need at all. Worse, this forces
> all drivers to hook up the default behaviour, breaking userspace if
> they forget to do that. And it forces us to export a bunch of core
> function just for those helpers.
> 
> And finally, these helpers are the last places using
> drm_atomic_legacy_backoff() and the implicit acquire_ctx.
> 
> This patch here just implements the new behaviour and updates the
> docs. Follow-up patches will garbage-collect all the dead code.
> 
> v2: Fixup docs even better!
> 
> v3: Make it actually work ...

Reviewed-by: Archit Taneja <architt at codeaurora.org>

> 
> Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
> ---
>   drivers/gpu/drm/drm_atomic.c        |  60 ++++++++++++++++++--
>   drivers/gpu/drm/drm_connector.c     |   6 +-
>   drivers/gpu/drm/drm_crtc_helper.c   |   3 +-
>   drivers/gpu/drm/drm_crtc_internal.h |   7 +++
>   drivers/gpu/drm/drm_mode_object.c   | 110 +++++++++++++++++++++++++++---------
>   include/drm/drm_connector.h         |  10 ++--
>   include/drm/drm_crtc.h              |   6 +-
>   include/drm/drm_plane.h             |   6 +-
>   8 files changed, 158 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 01192dd3ed79..0fd14aff7add 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1864,9 +1864,60 @@ static struct drm_pending_vblank_event *create_vblank_event(
>   	return e;
>   }
>   
> -static int atomic_set_prop(struct drm_atomic_state *state,
> -		struct drm_mode_object *obj, struct drm_property *prop,
> -		uint64_t prop_value)
> +int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> +				     struct drm_connector *connector,
> +				     int mode)
> +{
> +	struct drm_connector *tmp_connector;
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	int i, ret, old_mode = connector->dpms;
> +	bool active = false;
> +
> +	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
> +			       state->acquire_ctx);
> +	if (ret)
> +		return ret;
> +
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +	connector->dpms = mode;
> +
> +	crtc = connector->state->crtc;
> +	if (!crtc)
> +		goto out;
> +	ret = drm_atomic_add_affected_connectors(state, crtc);
> +	if (ret)
> +		goto out;
> +
> +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +	if (IS_ERR(crtc_state)) {
> +		ret = PTR_ERR(crtc_state);
> +		goto out;
> +	}
> +
> +	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
> +		if (new_conn_state->crtc != crtc)
> +			continue;
> +		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
> +			active = true;
> +			break;
> +		}
> +	}
> +
> +	crtc_state->active = active;
> +	ret = drm_atomic_commit(state);
> +out:
> +	if (ret != 0)
> +		connector->dpms = old_mode;
> +	return ret;
> +}
> +
> +int drm_atomic_set_property(struct drm_atomic_state *state,
> +			    struct drm_mode_object *obj,
> +			    struct drm_property *prop,
> +			    uint64_t prop_value)
>   {
>   	struct drm_mode_object *ref;
>   	int ret;
> @@ -2286,7 +2337,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
>   				goto out;
>   			}
>   
> -			ret = atomic_set_prop(state, obj, prop, prop_value);
> +			ret = drm_atomic_set_property(state, obj, prop,
> +						      prop_value);
>   			if (ret) {
>   				drm_mode_object_put(obj);
>   				goto out;
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 349104eadefe..12371f184019 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -717,9 +717,9 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
>    * 	drivers, it remaps to controlling the "ACTIVE" property on the CRTC the
>    * 	connector is linked to. Drivers should never set this property directly,
>    * 	it is handled by the DRM core by calling the &drm_connector_funcs.dpms
> - * 	callback. Atomic drivers should implement this hook using
> - * 	drm_atomic_helper_connector_dpms(). This is the only property standard
> - * 	connector property that userspace can change.
> + * 	callback. For atomic drivers the remapping to the "ACTIVE" property is
> + * 	implemented in the DRM core.  This is the only standard connector
> + * 	property that userspace can change.
>    * PATH:
>    * 	Connector path property to identify how this sink is physically
>    * 	connected. Used by DP MST. This should be set by calling
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 4afdf7902eda..eab36a460638 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -863,8 +863,7 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
>    * provided by the driver.
>    *
>    * This function is deprecated.  New drivers must implement atomic modeset
> - * support, for which this function is unsuitable. Instead drivers should use
> - * drm_atomic_helper_connector_dpms().
> + * support, where DPMS is handled in the DRM core.
>    *
>    * Returns:
>    * Always returns 0.
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index d077c5490041..a43582076b20 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -178,6 +178,13 @@ struct drm_minor;
>   int drm_atomic_debugfs_init(struct drm_minor *minor);
>   #endif
>   
> +int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> +				     struct drm_connector *connector,
> +				     int mode);
> +int drm_atomic_set_property(struct drm_atomic_state *state,
> +			    struct drm_mode_object *obj,
> +			    struct drm_property *prop,
> +			    uint64_t prop_value);
>   int drm_atomic_get_property(struct drm_mode_object *obj,
>   			    struct drm_property *property, uint64_t *val);
>   int drm_mode_atomic_ioctl(struct drm_device *dev,
> diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
> index 92743a796bf0..1055533792f3 100644
> --- a/drivers/gpu/drm/drm_mode_object.c
> +++ b/drivers/gpu/drm/drm_mode_object.c
> @@ -392,6 +392,83 @@ struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
>   	return NULL;
>   }
>   
> +static int set_property_legacy(struct drm_mode_object *obj,
> +			       struct drm_property *prop,
> +			       uint64_t prop_value)
> +{
> +	struct drm_device *dev = prop->dev;
> +	struct drm_mode_object *ref;
> +	int ret = -EINVAL;
> +
> +	if (!drm_property_change_valid_get(prop, prop_value, &ref))
> +		return -EINVAL;
> +
> +	drm_modeset_lock_all(dev);
> +	switch (obj->type) {
> +	case DRM_MODE_OBJECT_CONNECTOR:
> +		ret = drm_mode_connector_set_obj_prop(obj, prop,
> +						      prop_value);
> +		break;
> +	case DRM_MODE_OBJECT_CRTC:
> +		ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
> +		break;
> +	case DRM_MODE_OBJECT_PLANE:
> +		ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj),
> +						  prop, prop_value);
> +		break;
> +	}
> +	drm_property_change_valid_put(prop, ref);
> +	drm_modeset_unlock_all(dev);
> +
> +	return ret;
> +}
> +
> +static int set_property_atomic(struct drm_mode_object *obj,
> +			       struct drm_property *prop,
> +			       uint64_t prop_value)
> +{
> +	struct drm_device *dev = prop->dev;
> +	struct drm_atomic_state *state;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret;
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	state = drm_atomic_state_alloc(dev);
> +	if (!state)
> +		return -ENOMEM;
> +	state->acquire_ctx = &ctx;
> +retry:
> +	if (prop == state->dev->mode_config.dpms_property) {
> +		if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = drm_atomic_connector_commit_dpms(state,
> +						       obj_to_connector(obj),
> +						       prop_value);
> +	} else {
> +		ret = drm_atomic_set_property(state, obj, prop, prop_value);
> +		if (ret)
> +			goto out;
> +		ret = drm_atomic_commit(state);
> +	}
> +out:
> +	if (ret == -EDEADLK) {
> +		drm_atomic_state_clear(state);
> +		drm_modeset_backoff(&ctx);
> +		goto retry;
> +	}
> +
> +	drm_atomic_state_put(state);
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret;
> +}
> +
>   int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
>   				    struct drm_file *file_priv)
>   {
> @@ -399,18 +476,13 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
>   	struct drm_mode_object *arg_obj;
>   	struct drm_property *property;
>   	int ret = -EINVAL;
> -	struct drm_mode_object *ref;
>   
>   	if (!drm_core_check_feature(dev, DRIVER_MODESET))
>   		return -EINVAL;
>   
> -	drm_modeset_lock_all(dev);
> -
>   	arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
> -	if (!arg_obj) {
> -		ret = -ENOENT;
> -		goto out;
> -	}
> +	if (!arg_obj)
> +		return -ENOENT;
>   
>   	if (!arg_obj->properties)
>   		goto out_unref;
> @@ -419,28 +491,12 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
>   	if (!property)
>   		goto out_unref;
>   
> -	if (!drm_property_change_valid_get(property, arg->value, &ref))
> -		goto out_unref;
> -
> -	switch (arg_obj->type) {
> -	case DRM_MODE_OBJECT_CONNECTOR:
> -		ret = drm_mode_connector_set_obj_prop(arg_obj, property,
> -						      arg->value);
> -		break;
> -	case DRM_MODE_OBJECT_CRTC:
> -		ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
> -		break;
> -	case DRM_MODE_OBJECT_PLANE:
> -		ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
> -						  property, arg->value);
> -		break;
> -	}
> -
> -	drm_property_change_valid_put(property, ref);
> +	if (drm_drv_uses_atomic_modeset(property->dev))
> +		ret = set_property_atomic(arg_obj, property, arg->value);
> +	else
> +		ret = set_property_legacy(arg_obj, property, arg->value);
>   
>   out_unref:
>   	drm_mode_object_put(arg_obj);
> -out:
> -	drm_modeset_unlock_all(dev);
>   	return ret;
>   }
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 4bc088269d05..ea8da401c93c 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -382,8 +382,8 @@ struct drm_connector_funcs {
>   	 * implement the 4 level DPMS support on the connector any more, but
>   	 * instead only have an on/off "ACTIVE" property on the CRTC object.
>   	 *
> -	 * Drivers implementing atomic modeset should use
> -	 * drm_atomic_helper_connector_dpms() to implement this hook.
> +	 * This hook is not used by atomic drivers, remapping of the legacy DPMS
> +	 * property is entirely handled in the DRM core.
>   	 *
>   	 * RETURNS:
>   	 *
> @@ -480,11 +480,9 @@ struct drm_connector_funcs {
>   	 * This is the legacy entry point to update a property attached to the
>   	 * connector.
>   	 *
> -	 * Drivers implementing atomic modeset should use
> -	 * drm_atomic_helper_connector_set_property() to implement this hook.
> -	 *
>   	 * This callback is optional if the driver does not support any legacy
> -	 * driver-private properties.
> +	 * driver-private properties. For atomic drivers it is not used because
> +	 * property handling is done entirely in the DRM core.
>   	 *
>   	 * RETURNS:
>   	 *
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 3a911a64c257..9c01f94b393c 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -481,11 +481,9 @@ struct drm_crtc_funcs {
>   	 * This is the legacy entry point to update a property attached to the
>   	 * CRTC.
>   	 *
> -	 * Drivers implementing atomic modeset should use
> -	 * drm_atomic_helper_crtc_set_property() to implement this hook.
> -	 *
>   	 * This callback is optional if the driver does not support any legacy
> -	 * driver-private properties.
> +	 * driver-private properties. For atomic drivers it is not used because
> +	 * property handling is done entirely in the DRM core.
>   	 *
>   	 * RETURNS:
>   	 *
> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index 9ab3e7044812..204c213810df 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -233,11 +233,9 @@ struct drm_plane_funcs {
>   	 * This is the legacy entry point to update a property attached to the
>   	 * plane.
>   	 *
> -	 * Drivers implementing atomic modeset should use
> -	 * drm_atomic_helper_plane_set_property() to implement this hook.
> -	 *
>   	 * This callback is optional if the driver does not support any legacy
> -	 * driver-private properties.
> +	 * driver-private properties. For atomic drivers it is not used because
> +	 * property handling is done entirely in the DRM core.
>   	 *
>   	 * RETURNS:
>   	 *
> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


More information about the Intel-gfx mailing list