drm/amd/display: Add Underflow Asserts to dc

[Why]
For debugging underflow issues it can be useful to have asserts when the
underflow initially occurs.

[How]
Read the underflow status registers after actions that have a high risk
of causing underflow and assert that no underflow occurred. If underflow
occurred, clear the bit.

Signed-off-by: Thomas Lim <Thomas.Lim@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Thomas Lim 2019-04-29 16:05:42 -04:00 committed by Alex Deucher
parent 11cd74cdb9
commit 9ed43ef84d
5 changed files with 38 additions and 2 deletions

View File

@ -329,6 +329,7 @@ struct dc_debug_options {
int sr_exit_time_ns; int sr_exit_time_ns;
int sr_enter_plus_exit_time_ns; int sr_enter_plus_exit_time_ns;
int urgent_latency_ns; int urgent_latency_ns;
uint32_t underflow_assert_delay_us;
int percent_of_ideal_drambw; int percent_of_ideal_drambw;
int dram_clock_change_latency_ns; int dram_clock_change_latency_ns;
bool optimized_watermark; bool optimized_watermark;

View File

@ -360,6 +360,23 @@ void dcn10_log_hw_state(struct dc *dc,
DTN_INFO_END(); DTN_INFO_END();
} }
bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
if (tg->funcs->is_optc_underflow_occurred(tg)) {
tg->funcs->clear_optc_underflow(tg);
return true;
}
if (hubp->funcs->hubp_get_underflow_status(hubp)) {
hubp->funcs->hubp_clear_underflow(hubp);
return true;
}
return false;
}
static void enable_power_gating_plane( static void enable_power_gating_plane(
struct dce_hwseq *hws, struct dce_hwseq *hws,
bool enable) bool enable)
@ -2332,6 +2349,7 @@ static void dcn10_apply_ctx_for_surface(
{ {
int i; int i;
struct timing_generator *tg; struct timing_generator *tg;
uint32_t underflow_check_delay_us;
bool removed_pipe[4] = { false }; bool removed_pipe[4] = { false };
bool interdependent_update = false; bool interdependent_update = false;
struct pipe_ctx *top_pipe_to_program = struct pipe_ctx *top_pipe_to_program =
@ -2346,11 +2364,22 @@ static void dcn10_apply_ctx_for_surface(
interdependent_update = top_pipe_to_program->plane_state && interdependent_update = top_pipe_to_program->plane_state &&
top_pipe_to_program->plane_state->update_flags.bits.full_update; top_pipe_to_program->plane_state->update_flags.bits.full_update;
underflow_check_delay_us = dc->debug.underflow_assert_delay_us;
if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
if (interdependent_update) if (interdependent_update)
lock_all_pipes(dc, context, true); lock_all_pipes(dc, context, true);
else else
dcn10_pipe_control_lock(dc, top_pipe_to_program, true); dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
if (underflow_check_delay_us != 0xFFFFFFFF)
udelay(underflow_check_delay_us);
if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
if (num_planes == 0) { if (num_planes == 0) {
/* OTG blank before remove all front end */ /* OTG blank before remove all front end */
dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true); dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
@ -3022,7 +3051,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.disable_stream_gating = NULL, .disable_stream_gating = NULL,
.enable_stream_gating = NULL, .enable_stream_gating = NULL,
.setup_periodic_interrupt = dcn10_setup_periodic_interrupt, .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
.setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
.did_underflow_occur = dcn10_did_underflow_occur
}; };

View File

@ -71,6 +71,8 @@ void dcn10_get_hdr_visual_confirm_color(
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,
struct tg_color *color); struct tg_color *color);
bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx);
void update_dchubp_dpp( void update_dchubp_dpp(
struct dc *dc, struct dc *dc,
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,

View File

@ -560,6 +560,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.az_endpoint_mute_only = true, .az_endpoint_mute_only = true,
.recovery_enabled = false, /*enable this by default after testing.*/ .recovery_enabled = false, /*enable this by default after testing.*/
.max_downscale_src_width = 3840, .max_downscale_src_width = 3840,
.underflow_assert_delay_us = 0xFFFFFFFF,
}; };
static const struct dc_debug_options debug_defaults_diags = { static const struct dc_debug_options debug_defaults_diags = {
@ -569,7 +570,8 @@ static const struct dc_debug_options debug_defaults_diags = {
.clock_trace = true, .clock_trace = true,
.disable_stutter = true, .disable_stutter = true,
.disable_pplib_clock_request = true, .disable_pplib_clock_request = true,
.disable_pplib_wm_range = true .disable_pplib_wm_range = true,
.underflow_assert_delay_us = 0xFFFFFFFF,
}; };
static void dcn10_dpp_destroy(struct dpp **dpp) static void dcn10_dpp_destroy(struct dpp **dpp)

View File

@ -240,6 +240,7 @@ struct hw_sequencer_funcs {
void (*setup_periodic_interrupt)(struct pipe_ctx *pipe_ctx, enum vline_select vline); void (*setup_periodic_interrupt)(struct pipe_ctx *pipe_ctx, enum vline_select vline);
void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx); void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx);
bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx);
}; };