On 2022-03-09 14:19, Nicholas Kazlauskas wrote: > [Why] > To debug when p-state is being blocked and avoid PMFW hangs when > it does occur. > > [How] > Re-use the DCN10 hardware sequencer by adding a new interface for > verifying p-state high on the hubbub. The interface is mostly the > same as the DCN10 interface, but the bit definitions have changed for > the debug bus. > > Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@xxxxxxx> > Reviewed-by: Eric Yang <Eric.Yang2@xxxxxxx> Reviewed-by: Harry Wentland <harry.wentland@xxxxxxx> Harry > --- > .../drm/amd/display/dc/dcn10/dcn10_hubbub.c | 1 + > .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++- > .../drm/amd/display/dc/dcn30/dcn30_hubbub.c | 1 + > .../drm/amd/display/dc/dcn301/dcn301_hubbub.c | 1 + > .../drm/amd/display/dc/dcn31/dcn31_hubbub.c | 60 +++++++++++++++++++ > .../drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- > .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 2 + > 7 files changed, 73 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c > index f4f423d0b8c3..80595d7f060c 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c > @@ -940,6 +940,7 @@ static const struct hubbub_funcs hubbub1_funcs = { > .program_watermarks = hubbub1_program_watermarks, > .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, > .allow_self_refresh_control = hubbub1_allow_self_refresh_control, > + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, > }; > > void hubbub1_construct(struct hubbub *hubbub, > diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c > index bc9dd48258e3..c3e141c19a77 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c > @@ -1112,9 +1112,13 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc) > > void dcn10_verify_allow_pstate_change_high(struct dc *dc) > { > + struct hubbub *hubbub = dc->res_pool->hubbub; > static bool should_log_hw_state; /* prevent hw state log by default */ > > - if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) { > + if (!hubbub->funcs->verify_allow_pstate_change_high) > + return; > + > + if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) { > int i = 0; > > if (should_log_hw_state) > @@ -1123,8 +1127,8 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc) > TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES); > BREAK_TO_DEBUGGER(); > if (dcn10_hw_wa_force_recovery(dc)) { > - /*check again*/ > - if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) > + /*check again*/ > + if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) > BREAK_TO_DEBUGGER(); > } > } > diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c > index f4414de96acc..152c9c5733f1 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c > @@ -448,6 +448,7 @@ static const struct hubbub_funcs hubbub30_funcs = { > .program_watermarks = hubbub3_program_watermarks, > .allow_self_refresh_control = hubbub1_allow_self_refresh_control, > .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, > + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, > .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, > .force_pstate_change_control = hubbub3_force_pstate_change_control, > .init_watermarks = hubbub3_init_watermarks, > diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c > index 1e3bd2e9cdcc..a046664e2031 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c > @@ -60,6 +60,7 @@ static const struct hubbub_funcs hubbub301_funcs = { > .program_watermarks = hubbub3_program_watermarks, > .allow_self_refresh_control = hubbub1_allow_self_refresh_control, > .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, > + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, > .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, > .force_pstate_change_control = hubbub3_force_pstate_change_control, > .hubbub_read_state = hubbub2_read_state, > diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c > index 5e3bcaf12cac..3e6d6ebd199e 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c > @@ -949,6 +949,65 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub, > } > } > > +static bool hubbub31_verify_allow_pstate_change_high(struct hubbub *hubbub) > +{ > + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); > + > + /* > + * Pstate latency is ~20us so if we wait over 40us and pstate allow > + * still not asserted, we are probably stuck and going to hang > + */ > + const unsigned int pstate_wait_timeout_us = 100; > + const unsigned int pstate_wait_expected_timeout_us = 40; > + > + static unsigned int max_sampled_pstate_wait_us; /* data collection */ > + static bool forced_pstate_allow; /* help with revert wa */ > + > + unsigned int debug_data = 0; > + unsigned int i; > + > + if (forced_pstate_allow) { > + /* we hacked to force pstate allow to prevent hang last time > + * we verify_allow_pstate_change_high. so disable force > + * here so we can check status > + */ > + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, > + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, > + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); > + forced_pstate_allow = false; > + } > + > + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub2->debug_test_index_pstate); > + > + for (i = 0; i < pstate_wait_timeout_us; i++) { > + debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); > + > + /* Debug bit is specific to ASIC. */ > + if (debug_data & (1 << 26)) { > + if (i > pstate_wait_expected_timeout_us) > + DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i); > + return true; > + } > + if (max_sampled_pstate_wait_us < i) > + max_sampled_pstate_wait_us = i; > + > + udelay(1); > + } > + > + /* force pstate allow to prevent system hang > + * and break to debugger to investigate > + */ > + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, > + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, > + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); > + forced_pstate_allow = true; > + > + DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n", > + debug_data); > + > + return false; > +} > + > static const struct hubbub_funcs hubbub31_funcs = { > .update_dchub = hubbub2_update_dchub, > .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, > @@ -961,6 +1020,7 @@ static const struct hubbub_funcs hubbub31_funcs = { > .program_watermarks = hubbub31_program_watermarks, > .allow_self_refresh_control = hubbub1_allow_self_refresh_control, > .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, > + .verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high, > .program_det_size = dcn31_program_det_size, > .program_compbuf_size = dcn31_program_compbuf_size, > .init_crb = dcn31_init_crb, > diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c > index 7dbe301a994a..89b7b6b7254a 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c > @@ -1011,7 +1011,7 @@ static const struct dc_debug_options debug_defaults_drv = { > .max_downscale_src_width = 4096,/*upto true 4K*/ > .disable_pplib_wm_range = false, > .scl_reset_length10 = true, > - .sanity_checks = false, > + .sanity_checks = true, > .underflow_assert_delay_us = 0xFFFFFFFF, > .dwb_fi_phase = -1, // -1 = disable, > .dmub_command_table = true, > diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h > index 713f5558f5e1..9195dec294c2 100644 > --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h > +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h > @@ -154,6 +154,8 @@ struct hubbub_funcs { > bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub); > void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow); > > + bool (*verify_allow_pstate_change_high)(struct hubbub *hubbub); > + > void (*apply_DEDCN21_147_wa)(struct hubbub *hubbub); > > void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub);