lkml.org 
[lkml]   [2022]   [Apr]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 001/219] drm/amd/display: Add pstate verification and recovery for DCN31
    Date
    From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>

    commit e7031d8258f1b4d6d50e5e5b5d92ba16f66eb8b4 upstream.

    [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@amd.com>
    Reviewed-by: Eric Yang <Eric.Yang2@amd.com>
    Reviewed-by: Harry Wentland <harry.wentland@amd.com>
    Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 1
    drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +-
    drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c | 1
    drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c | 1
    drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c | 60 ++++++++++++++
    drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2
    drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 2
    7 files changed, 73 insertions(+), 4 deletions(-)

    --- 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
    .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,
    --- 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(s

    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_hi
    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();
    }
    }
    --- 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 hubbub3
    .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,
    --- 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 hubbub3
    .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,
    --- 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(
    }
    }

    +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 hubbub3
    .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,
    --- 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 deb
    .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,
    --- 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);

    \
     
     \ /
      Last update: 2022-04-18 14:17    [W:4.385 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site