[PATCH 1/2] drm/amd/display: Use private obj helpers for dm_atomic_state

Li, Sun peng (Leo) Sunpeng.Li at amd.com
Tue Nov 27 21:20:39 UTC 2018



On 2018-11-22 12:34 p.m., Nicholas Kazlauskas wrote:
> [Why]
> Two non-blocking commits in succession can result in a sequence where
> the same dc->current_state is queried for both commits.
> 
> 1. 1st commit -> check -> commit -> swaps atomic state -> queues work
> 2. 2nd commit -> check -> commit -> swaps atomic state -> queues work
> 3. 1st commit work finishes
> 
> The issue with this sequence is that the same dc->current_state is
> read in both atomic checks. If the first commit modifies streams or
> planes those will be missing from the dc->current_state for the
> second atomic check. This result in many stream and plane errors in
> atomic commit tail.
> 
> [How]
> The driver still needs to track old to new state to determine if the
> commit in its current implementation. Updating the dc_state in
> atomic tail is wrong since the dc_state swap should be happening as
> part of drm_atomic_helper_swap_state *before* the worker queue kicks
> its work off.
> 
> The simplest replacement for the subclassing (which doesn't properly
> manage the old to new atomic state swap) is to use the drm private
> object helpers. While some of the dc_state members could be merged
> into dm_crtc_state or dm_plane_state and copied over that way it is
> easier for now to just treat the whole dc_state structure as a single
> private object.
> 
> This allows amdgpu_dm to drop the dc->current_state copy from within
> atomic check. It's replaced by a copy from the current atomic state
> which is propagated correctly for the sequence described above.
> 
> Since access to the dm_state private object is now locked this should
> also fix issues that could arise if submitting non-blocking commits
> from different threads.
> 
> Cc: Harry Wentland <harry.wentland at amd.com>
> Cc: Leo Li <sunpeng.li at amd.com>
> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

Patch 1/2 is
Reviewed-by: Leo Li <sunpeng.li at amd.com>

Leo
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 290 ++++++++++++++----
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  13 +-
>   2 files changed, 234 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 8433d31cdea8..3ae438d9849f 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -968,45 +968,6 @@ const struct amdgpu_ip_block_version dm_ip_block =
>   };
>   
>   
> -static struct drm_atomic_state *
> -dm_atomic_state_alloc(struct drm_device *dev)
> -{
> -	struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
> -
> -	if (!state)
> -		return NULL;
> -
> -	if (drm_atomic_state_init(dev, &state->base) < 0)
> -		goto fail;
> -
> -	return &state->base;
> -
> -fail:
> -	kfree(state);
> -	return NULL;
> -}
> -
> -static void
> -dm_atomic_state_clear(struct drm_atomic_state *state)
> -{
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
> -
> -	if (dm_state->context) {
> -		dc_release_state(dm_state->context);
> -		dm_state->context = NULL;
> -	}
> -
> -	drm_atomic_state_default_clear(state);
> -}
> -
> -static void
> -dm_atomic_state_alloc_free(struct drm_atomic_state *state)
> -{
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
> -	drm_atomic_state_default_release(state);
> -	kfree(dm_state);
> -}
> -
>   /**
>    * DOC: atomic
>    *
> @@ -1018,9 +979,6 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
>   	.output_poll_changed = drm_fb_helper_output_poll_changed,
>   	.atomic_check = amdgpu_dm_atomic_check,
>   	.atomic_commit = amdgpu_dm_atomic_commit,
> -	.atomic_state_alloc = dm_atomic_state_alloc,
> -	.atomic_state_clear = dm_atomic_state_clear,
> -	.atomic_state_free = dm_atomic_state_alloc_free
>   };
>   
>   static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
> @@ -1542,8 +1500,117 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
>   }
>   #endif
>   
> +/*
> + * Acquires the lock for the atomic state object and returns
> + * the new atomic state.
> + *
> + * This should only be called during atomic check.
> + */
> +static int dm_atomic_get_state(struct drm_atomic_state *state,
> +			       struct dm_atomic_state **dm_state)
> +{
> +	struct drm_device *dev = state->dev;
> +	struct amdgpu_device *adev = dev->dev_private;
> +	struct amdgpu_display_manager *dm = &adev->dm;
> +	struct drm_private_state *priv_state;
> +	int ret;
> +
> +	if (*dm_state)
> +		return 0;
> +
> +	ret = drm_modeset_lock(&dm->atomic_obj_lock, state->acquire_ctx);
> +	if (ret)
> +		return ret;
> +
> +	priv_state = drm_atomic_get_private_obj_state(state, &dm->atomic_obj);
> +	if (IS_ERR(priv_state))
> +		return PTR_ERR(priv_state);
> +
> +	*dm_state = to_dm_atomic_state(priv_state);
> +
> +	return 0;
> +}
> +
> +struct dm_atomic_state *
> +dm_atomic_get_new_state(struct drm_atomic_state *state)
> +{
> +	struct drm_device *dev = state->dev;
> +	struct amdgpu_device *adev = dev->dev_private;
> +	struct amdgpu_display_manager *dm = &adev->dm;
> +	struct drm_private_obj *obj;
> +	struct drm_private_state *new_obj_state;
> +	int i;
> +
> +	for_each_new_private_obj_in_state(state, obj, new_obj_state, i) {
> +		if (obj->funcs == dm->atomic_obj.funcs)
> +			return to_dm_atomic_state(new_obj_state);
> +	}
> +
> +	return NULL;
> +}
> +
> +struct dm_atomic_state *
> +dm_atomic_get_old_state(struct drm_atomic_state *state)
> +{
> +	struct drm_device *dev = state->dev;
> +	struct amdgpu_device *adev = dev->dev_private;
> +	struct amdgpu_display_manager *dm = &adev->dm;
> +	struct drm_private_obj *obj;
> +	struct drm_private_state *old_obj_state;
> +	int i;
> +
> +	for_each_old_private_obj_in_state(state, obj, old_obj_state, i) {
> +		if (obj->funcs == dm->atomic_obj.funcs)
> +			return to_dm_atomic_state(old_obj_state);
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct drm_private_state *
> +dm_atomic_duplicate_state(struct drm_private_obj *obj)
> +{
> +	struct dm_atomic_state *old_state, *new_state;
> +
> +	new_state = kzalloc(sizeof(*new_state), GFP_KERNEL);
> +	if (!new_state)
> +		return NULL;
> +
> +	__drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
> +
> +	new_state->context = dc_create_state();
> +	if (!new_state->context) {
> +		kfree(new_state);
> +		return NULL;
> +	}
> +
> +	old_state = to_dm_atomic_state(obj->state);
> +	if (old_state && old_state->context)
> +		dc_resource_state_copy_construct(old_state->context,
> +						 new_state->context);
> +
> +	return &new_state->base;
> +}
> +
> +static void dm_atomic_destroy_state(struct drm_private_obj *obj,
> +				    struct drm_private_state *state)
> +{
> +	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
> +
> +	if (dm_state && dm_state->context)
> +		dc_release_state(dm_state->context);
> +
> +	kfree(dm_state);
> +}
> +
> +static struct drm_private_state_funcs dm_atomic_state_funcs = {
> +	.atomic_duplicate_state = dm_atomic_duplicate_state,
> +	.atomic_destroy_state = dm_atomic_destroy_state,
> +};
> +
>   static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
>   {
> +	struct dm_atomic_state *state;
>   	int r;
>   
>   	adev->mode_info.mode_config_initialized = true;
> @@ -1561,6 +1628,24 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
>   
>   	adev->ddev->mode_config.fb_base = adev->gmc.aper_base;
>   
> +	drm_modeset_lock_init(&adev->dm.atomic_obj_lock);
> +
> +	state = kzalloc(sizeof(*state), GFP_KERNEL);
> +	if (!state)
> +		return -ENOMEM;
> +
> +	state->context = dc_create_state();
> +	if (!state->context) {
> +		kfree(state);
> +		return -ENOMEM;
> +	}
> +
> +	dc_resource_state_copy_construct_current(adev->dm.dc, state->context);
> +
> +	drm_atomic_private_obj_init(&adev->dm.atomic_obj,
> +				    &state->base,
> +				    &dm_atomic_state_funcs);
> +
>   	r = amdgpu_display_modeset_create_props(adev);
>   	if (r)
>   		return r;
> @@ -1849,6 +1934,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
>   static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
>   {
>   	drm_mode_config_cleanup(dm->ddev);
> +	drm_atomic_private_obj_fini(&dm->atomic_obj);
>   	return;
>   }
>   
> @@ -4274,6 +4360,20 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
>   						 acrtc->crtc_id);
>   }
>   
> +struct dc_stream_status *dc_state_get_stream_status(
> +	struct dc_state *state,
> +	struct dc_stream_state *stream)
> +{
> +	uint8_t i;
> +
> +	for (i = 0; i < state->stream_count; i++) {
> +		if (stream == state->streams[i])
> +			return &state->stream_status[i];
> +	}
> +
> +	return NULL;
> +}
> +
>   /*
>    * Executes flip
>    *
> @@ -4477,6 +4577,7 @@ static bool commit_planes_to_stream(
>   }
>   
>   static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
> +				    struct dc_state *dc_state,
>   				    struct drm_device *dev,
>   				    struct amdgpu_display_manager *dm,
>   				    struct drm_crtc *pcrtc,
> @@ -4493,7 +4594,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
>   	struct dm_crtc_state *dm_old_crtc_state =
>   			to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
>   	int planes_count = 0;
>   	unsigned long flags;
>   
> @@ -4554,7 +4654,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   				crtc,
>   				fb,
>   				(uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank,
> -				dm_state->context);
> +				dc_state);
>   		}
>   
>   	}
> @@ -4579,7 +4679,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   							planes_count,
>   							acrtc_state,
>   							dm_old_crtc_state,
> -							dm_state->context))
> +							dc_state))
>   			dm_error("%s: Failed to attach plane!\n", __func__);
>   	} else {
>   		/*TODO BUG Here should go disable planes on CRTC. */
> @@ -4647,6 +4747,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   	struct amdgpu_device *adev = dev->dev_private;
>   	struct amdgpu_display_manager *dm = &adev->dm;
>   	struct dm_atomic_state *dm_state;
> +	struct dc_state *dc_state = NULL, *dc_state_temp = NULL;
>   	uint32_t i, j;
>   	struct drm_crtc *crtc;
>   	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> @@ -4659,7 +4760,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   
>   	drm_atomic_helper_update_legacy_modeset_state(dev, state);
>   
> -	dm_state = to_dm_atomic_state(state);
> +	dm_state = dm_atomic_get_new_state(state);
> +	if (dm_state && dm_state->context) {
> +		dc_state = dm_state->context;
> +	} else {
> +		/* No state changes, retain current state. */
> +		dc_state_temp = dc_create_state();
> +		ASSERT(dc_state_temp);
> +		dc_state = dc_state_temp;
> +		dc_resource_state_copy_construct_current(dm->dc, dc_state);
> +	}
>   
>   	/* update changed items */
>   	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> @@ -4732,9 +4842,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   		}
>   	} /* for_each_crtc_in_state() */
>   
> -	if (dm_state->context) {
> -		dm_enable_per_frame_crtc_master_sync(dm_state->context);
> -		WARN_ON(!dc_commit_state(dm->dc, dm_state->context));
> +	if (dc_state) {
> +		dm_enable_per_frame_crtc_master_sync(dc_state);
> +		WARN_ON(!dc_commit_state(dm->dc, dc_state));
>   	}
>   
>   	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> @@ -4746,6 +4856,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   			const struct dc_stream_status *status =
>   					dc_stream_get_status(dm_new_crtc_state->stream);
>   
> +			if (!status)
> +				status = dc_state_get_stream_status(dc_state,
> +								    dm_new_crtc_state->stream);
> +
>   			if (!status)
>   				DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc);
>   			else
> @@ -4828,7 +4942,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>   
>   		if (dm_new_crtc_state->stream)
> -			amdgpu_dm_commit_planes(state, dev, dm, crtc, &wait_for_vblank);
> +			amdgpu_dm_commit_planes(state, dc_state, dev,
> +						dm, crtc, &wait_for_vblank);
>   	}
>   
>   
> @@ -4868,6 +4983,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   	for (i = 0; i < crtc_disable_count; i++)
>   		pm_runtime_put_autosuspend(dev->dev);
>   	pm_runtime_mark_last_busy(dev->dev);
> +
> +	if (dc_state_temp)
> +		dc_release_state(dc_state_temp);
>   }
>   
>   
> @@ -5054,11 +5172,11 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
>   				 bool enable,
>   				 bool *lock_and_validation_needed)
>   {
> +	struct dm_atomic_state *dm_state = NULL;
>   	struct drm_crtc *crtc;
>   	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>   	int i;
>   	struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
>   	struct dc_stream_state *new_stream;
>   	int ret = 0;
>   
> @@ -5156,6 +5274,10 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
>   			if (!dm_old_crtc_state->stream)
>   				goto next_crtc;
>   
> +			ret = dm_atomic_get_state(state, &dm_state);
> +			if (ret)
> +				goto fail;
> +
>   			DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n",
>   					crtc->base.id);
>   
> @@ -5190,6 +5312,10 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
>   
>   				WARN_ON(dm_new_crtc_state->stream);
>   
> +				ret = dm_atomic_get_state(state, &dm_state);
> +				if (ret)
> +					goto fail;
> +
>   				dm_new_crtc_state->stream = new_stream;
>   
>   				dc_stream_retain(new_stream);
> @@ -5264,12 +5390,13 @@ static int dm_update_planes_state(struct dc *dc,
>   				  bool enable,
>   				  bool *lock_and_validation_needed)
>   {
> +
> +	struct dm_atomic_state *dm_state = NULL;
>   	struct drm_crtc *new_plane_crtc, *old_plane_crtc;
>   	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>   	struct drm_plane *plane;
>   	struct drm_plane_state *old_plane_state, *new_plane_state;
>   	struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
>   	struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
>   	int i ;
>   	/* TODO return page_flip_needed() function */
> @@ -5307,6 +5434,10 @@ static int dm_update_planes_state(struct dc *dc,
>   			DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n",
>   					plane->base.id, old_plane_crtc->base.id);
>   
> +			ret = dm_atomic_get_state(state, &dm_state);
> +			if (ret)
> +				return ret;
> +
>   			if (!dc_remove_plane_from_context(
>   					dc,
>   					dm_old_crtc_state->stream,
> @@ -5361,6 +5492,12 @@ static int dm_update_planes_state(struct dc *dc,
>   				return ret;
>   			}
>   
> +			ret = dm_atomic_get_state(state, &dm_state);
> +			if (ret) {
> +				dc_plane_state_release(dc_new_plane_state);
> +				return ret;
> +			}
> +
>   			/*
>   			 * Any atomic check errors that occur after this will
>   			 * not need a release. The plane state will be attached
> @@ -5392,11 +5529,14 @@ static int dm_update_planes_state(struct dc *dc,
>   
>   	return ret;
>   }
> -enum surface_update_type dm_determine_update_type_for_commit(struct dc *dc, struct drm_atomic_state *state)
> -{
> -
>   
> -	int i, j, num_plane;
> +static int
> +dm_determine_update_type_for_commit(struct dc *dc,
> +				    struct drm_atomic_state *state,
> +				    enum surface_update_type *out_type)
> +{
> +	struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL;
> +	int i, j, num_plane, ret = 0;
>   	struct drm_plane_state *old_plane_state, *new_plane_state;
>   	struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
>   	struct drm_crtc *new_plane_crtc, *old_plane_crtc;
> @@ -5416,7 +5556,7 @@ enum surface_update_type dm_determine_update_type_for_commit(struct dc *dc, stru
>   		DRM_ERROR("Plane or surface update failed to allocate");
>   		/* Set type to FULL to avoid crashing in DC*/
>   		update_type = UPDATE_TYPE_FULL;
> -		goto ret;
> +		goto cleanup;
>   	}
>   
>   	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> @@ -5470,27 +5610,40 @@ enum surface_update_type dm_determine_update_type_for_commit(struct dc *dc, stru
>   			}
>   
>   			if (num_plane > 0) {
> -				status = dc_stream_get_status(new_dm_crtc_state->stream);
> +				ret = dm_atomic_get_state(state, &dm_state);
> +				if (ret)
> +					goto cleanup;
> +
> +				old_dm_state = dm_atomic_get_old_state(state);
> +				if (!old_dm_state) {
> +					ret = -EINVAL;
> +					goto cleanup;
> +				}
> +
> +				status = dc_state_get_stream_status(old_dm_state->context,
> +								    new_dm_crtc_state->stream);
> +
>   				update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane,
>   										  &stream_update, status);
>   
>   				if (update_type > UPDATE_TYPE_MED) {
>   					update_type = UPDATE_TYPE_FULL;
> -					goto ret;
> +					goto cleanup;
>   				}
>   			}
>   
>   		} else if (!new_dm_crtc_state->stream && old_dm_crtc_state->stream) {
>   			update_type = UPDATE_TYPE_FULL;
> -			goto ret;
> +			goto cleanup;
>   		}
>   	}
>   
> -ret:
> +cleanup:
>   	kfree(updates);
>   	kfree(surface);
>   
> -	return update_type;
> +	*out_type = update_type;
> +	return ret;
>   }
>   
>   /**
> @@ -5522,8 +5675,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   				  struct drm_atomic_state *state)
>   {
>   	struct amdgpu_device *adev = dev->dev_private;
> +	struct dm_atomic_state *dm_state = NULL;
>   	struct dc *dc = adev->dm.dc;
> -	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
>   	struct drm_connector *connector;
>   	struct drm_connector_state *old_con_state, *new_con_state;
>   	struct drm_crtc *crtc;
> @@ -5564,10 +5717,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   			goto fail;
>   	}
>   
> -	dm_state->context = dc_create_state();
> -	ASSERT(dm_state->context);
> -	dc_resource_state_copy_construct_current(dc, dm_state->context);
> -
>   	/* Remove exiting planes if they are modified */
>   	ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed);
>   	if (ret) {
> @@ -5620,7 +5769,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   		lock_and_validation_needed = true;
>   	}
>   
> -	update_type = dm_determine_update_type_for_commit(dc, state);
> +	ret = dm_determine_update_type_for_commit(dc, state, &update_type);
> +	if (ret)
> +		goto fail;
>   
>   	if (overall_update_type < update_type)
>   		overall_update_type = update_type;
> @@ -5638,6 +5789,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   
>   
>   	if (overall_update_type > UPDATE_TYPE_FAST) {
> +		ret = dm_atomic_get_state(state, &dm_state);
> +		if (ret)
> +			goto fail;
>   
>   		ret = do_aquire_global_lock(dev, state);
>   		if (ret)
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 607c3cdd7d0c..c8fd95950d0c 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -111,6 +111,17 @@ struct amdgpu_display_manager {
>   	struct drm_device *ddev;
>   	u16 display_indexes_num;
>   
> +	/**
> +	 * @atomic_obj
> +	 *
> +	 * In combination with &dm_atomic_state it helps manage
> +	 * global atomic state that doesn't map cleanly into existing
> +	 * drm resources, like &dc_context.
> +	 */
> +	struct drm_private_obj atomic_obj;
> +
> +	struct drm_modeset_lock atomic_obj_lock;
> +
>   	/**
>   	 * @irq_handler_list_low_tab:
>   	 *
> @@ -239,7 +250,7 @@ struct dm_crtc_state {
>   #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
>   
>   struct dm_atomic_state {
> -	struct drm_atomic_state base;
> +	struct drm_private_state base;
>   
>   	struct dc_state *context;
>   };
> 


More information about the amd-gfx mailing list