Commit 9b216b7e authored by Alvin Lee's avatar Alvin Lee Committed by Alex Deucher
Browse files

drm/amd/display: Retain phantom plane/stream if validation fails



[Description]
- If we fail validation, we should retain the phantom
  stream/planes
- Full updates assume that phantom pipes will be fully
  removed, but if validation fails we keep the phantom
  pipes
- Therefore we have to retain the plane/stream if validation
  fails (since the refcount is decremented before validation,
  and the expectation is that it's fully freed when the  old
  dc_state is released)

Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarBrian Chang <Brian.Chang@amd.com>
Signed-off-by: default avatarAlvin Lee <Alvin.Lee2@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e49c5e12
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -3098,6 +3098,19 @@ static bool update_planes_and_stream_state(struct dc *dc,

	if (update_type == UPDATE_TYPE_FULL) {
		if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
			/* For phantom pipes we remove and create a new set of phantom pipes
			 * for each full update (because we don't know if we'll need phantom
			 * pipes until after the first round of validation). However, if validation
			 * fails we need to keep the existing phantom pipes (because we don't update
			 * the dc->current_state).
			 *
			 * The phantom stream/plane refcount is decremented for validation because
			 * we assume it'll be removed (the free comes when the dc_state is freed),
			 * but if validation fails we have to increment back the refcount so it's
			 * consistent.
			 */
			if (dc->res_pool->funcs->retain_phantom_pipes)
				dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state);
			BREAK_TO_DEBUGGER();
			goto fail;
		}
+22 −0
Original line number Diff line number Diff line
@@ -1721,6 +1721,27 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
	return phantom_stream;
}

void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context)
{
	int i;
	struct dc_plane_state *phantom_plane = NULL;
	struct dc_stream_state *phantom_stream = NULL;

	for (i = 0; i < dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];

		if (!pipe->top_pipe && !pipe->prev_odm_pipe &&
				pipe->plane_state && pipe->stream &&
				pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
			phantom_plane = pipe->plane_state;
			phantom_stream = pipe->stream;

			dc_plane_state_retain(phantom_plane);
			dc_stream_retain(phantom_stream);
		}
	}
}

// return true if removed piped from ctx, false otherwise
bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context)
{
@@ -2033,6 +2054,7 @@ static struct resource_funcs dcn32_res_pool_funcs = {
	.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
	.add_phantom_pipes = dcn32_add_phantom_pipes,
	.remove_phantom_pipes = dcn32_remove_phantom_pipes,
	.retain_phantom_pipes = dcn32_retain_phantom_pipes,
};


+3 −0
Original line number Diff line number Diff line
@@ -83,6 +83,9 @@ bool dcn32_release_post_bldn_3dlut(
bool dcn32_remove_phantom_pipes(struct dc *dc,
		struct dc_state *context);

void dcn32_retain_phantom_pipes(struct dc *dc,
		struct dc_state *context);

void dcn32_add_phantom_pipes(struct dc *dc,
		struct dc_state *context,
		display_e2e_pipe_params_st *pipes,
+1 −0
Original line number Diff line number Diff line
@@ -1621,6 +1621,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
	.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
	.add_phantom_pipes = dcn32_add_phantom_pipes,
	.remove_phantom_pipes = dcn32_remove_phantom_pipes,
	.retain_phantom_pipes = dcn32_retain_phantom_pipes,
};


+1 −0
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ struct resource_funcs {
            unsigned int index);

	bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context);
	void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context);
	void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
};