drm/amd/display: Use the largest vready_offset in pipe group
[ Upstream commit 5842abd985b792a3b13a89b6dae4869b56656c92 ] [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: Dillon Varone <Dillon.Varone@amd.com> Acked-by: Jasdeep Dhillon <jdhillon@amd.com> Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
eff45bfbc2
commit
6209542869
@@ -804,6 +804,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,
|
||||
@@ -838,7 +864,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,
|
||||
@@ -2776,7 +2802,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);
|
||||
|
||||
@@ -1564,6 +1564,31 @@ static void dcn20_update_dchubp_dpp(
|
||||
hubp->funcs->set_blank(hubp, false);
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -1582,7 +1607,7 @@ static void dcn20_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);
|
||||
@@ -1875,7 +1900,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);
|
||||
|
||||
Reference in New Issue
Block a user