[PATCH] drm/amd/display: Add pstate verification and recovery for DCN31

Harry Wentland harry.wentland at amd.com
Wed Mar 9 20:31:02 UTC 2022


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 at amd.com>
> Reviewed-by: Eric Yang <Eric.Yang2 at amd.com>

Reviewed-by: Harry Wentland <harry.wentland at amd.com>

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);



More information about the amd-gfx mailing list