Commit 5842abd9 authored by Wesley Chalmers's avatar Wesley Chalmers Committed by Alex Deucher
Browse files

drm/amd/display: Use the largest vready_offset in pipe group



[WHY]
Corruption can occur in LB if vready_offset is not large enough.
DML calculates vready_offset for each pipe, but we currently select the
top pipe's vready_offset, which is not necessarily enough for all pipes
in the group.

[HOW]
Wherever program_global_sync is currently called, iterate through the
entire pipe group and find the highest vready_offset.

Reviewed-by: default avatarDillon Varone <Dillon.Varone@amd.com>
Acked-by: default avatarJasdeep Dhillon <jdhillon@amd.com>
Signed-off-by: default avatarWesley Chalmers <Wesley.Chalmers@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 725a521a
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -869,6 +869,32 @@ static void false_optc_underflow_wa(
		tg->funcs->clear_optc_underflow(tg);
}

static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
{
	struct pipe_ctx *other_pipe;
	int vready_offset = pipe->pipe_dlg_param.vready_offset;

	/* Always use the largest vready_offset of all connected pipes */
	for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}

	return vready_offset;
}

enum dc_status dcn10_enable_stream_timing(
		struct pipe_ctx *pipe_ctx,
		struct dc_state *context,
@@ -912,7 +938,7 @@ enum dc_status dcn10_enable_stream_timing(
	pipe_ctx->stream_res.tg->funcs->program_timing(
			pipe_ctx->stream_res.tg,
			&stream->timing,
			pipe_ctx->pipe_dlg_param.vready_offset,
			calculate_vready_offset_for_group(pipe_ctx),
			pipe_ctx->pipe_dlg_param.vstartup_start,
			pipe_ctx->pipe_dlg_param.vupdate_offset,
			pipe_ctx->pipe_dlg_param.vupdate_width,
@@ -2908,7 +2934,7 @@ void dcn10_program_pipe(

		pipe_ctx->stream_res.tg->funcs->program_global_sync(
				pipe_ctx->stream_res.tg,
				pipe_ctx->pipe_dlg_param.vready_offset,
				calculate_vready_offset_for_group(pipe_ctx),
				pipe_ctx->pipe_dlg_param.vstartup_start,
				pipe_ctx->pipe_dlg_param.vupdate_offset,
				pipe_ctx->pipe_dlg_param.vupdate_width);
+27 −2
Original line number Diff line number Diff line
@@ -1652,6 +1652,31 @@ static void dcn20_update_dchubp_dpp(
		hubp->funcs->phantom_hubp_post_enable(hubp);
}

static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
{
	struct pipe_ctx *other_pipe;
	int vready_offset = pipe->pipe_dlg_param.vready_offset;

	/* Always use the largest vready_offset of all connected pipes */
	for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}
	for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) {
		if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
			vready_offset = other_pipe->pipe_dlg_param.vready_offset;
	}

	return vready_offset;
}

static void dcn20_program_pipe(
		struct dc *dc,
@@ -1670,7 +1695,7 @@ static void dcn20_program_pipe(
			&& !pipe_ctx->prev_odm_pipe) {
		pipe_ctx->stream_res.tg->funcs->program_global_sync(
				pipe_ctx->stream_res.tg,
				pipe_ctx->pipe_dlg_param.vready_offset,
				calculate_vready_offset_for_group(pipe_ctx),
				pipe_ctx->pipe_dlg_param.vstartup_start,
				pipe_ctx->pipe_dlg_param.vupdate_offset,
				pipe_ctx->pipe_dlg_param.vupdate_width);
@@ -2067,7 +2092,7 @@ bool dcn20_update_bandwidth(

			pipe_ctx->stream_res.tg->funcs->program_global_sync(
					pipe_ctx->stream_res.tg,
					pipe_ctx->pipe_dlg_param.vready_offset,
					calculate_vready_offset_for_group(pipe_ctx),
					pipe_ctx->pipe_dlg_param.vstartup_start,
					pipe_ctx->pipe_dlg_param.vupdate_offset,
					pipe_ctx->pipe_dlg_param.vupdate_width);