From: Alvin Lee <alvin.lee2@xxxxxxx> [Description] Refactor code and move fpo_in_use into stream_status to avoid unexpected changes to previous dc_state (i.e., current_state). Since stream pointers are shared between current and new dc_states, updating parameters of one stream will update the other as well which causes unexpected behaviors (i.e., checking that fpo_in_use isn't set in previous state and set in the new state is invalid). To avoid incorrect updates to current_state, move the fpo_in_use flag into dc_stream_status since stream_status is owned by dc and are not shared between different dc_states. Reviewed-by: Samson Tam <samson.tam@xxxxxxx> Acked-by: Zaeem Mohamed <zaeem.mohamed@xxxxxxx> Signed-off-by: Alvin Lee <alvin.lee2@xxxxxxx> --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 12 +++++++++-- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +- .../drm/amd/display/dc/dml/dcn30/dcn30_fpu.c | 6 +++++- .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 15 +++++++++++--- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 20 ++++++++++++++----- .../dc/resource/dcn30/dcn30_resource.c | 8 +++++++- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 364ef9ae32f1..0e70b95573ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -427,6 +427,7 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. Reenable it. uint8_t visual_confirm_enabled; int pipe_idx = 0; + struct dc_stream_status *stream_status = NULL; if (dc == NULL) return false; @@ -443,6 +444,7 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + stream_status = NULL; if (!pipe->stream) continue; @@ -450,7 +452,8 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru * that does not use FAMS, we are in an FPO + VActive scenario. * Assign vactive stretch margin in this case. */ - if (!pipe->stream->fpo_in_use) { + stream_status = dc_state_get_stream_status(context, pipe->stream); + if (stream_status && !stream_status->fpo_in_use) { cmd.fw_assisted_mclk_switch.config_data.vactive_stretch_margin_us = dc->debug.fpo_vactive_margin_us; break; } @@ -461,7 +464,12 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru for (i = 0, k = 0; context && i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (resource_is_pipe_type(pipe, OTG_MASTER) && pipe->stream->fpo_in_use) { + stream_status = NULL; + if (!resource_is_pipe_type(pipe, OTG_MASTER)) + continue; + + stream_status = dc_state_get_stream_status(context, pipe->stream); + if (stream_status && stream_status->fpo_in_use) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; uint8_t min_refresh_in_hz = (pipe->stream->timing.min_refresh_in_uhz + 999999) / 1000000; diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 1469a20f2511..8ebd7e9e776e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -59,6 +59,7 @@ struct dc_stream_status { struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; bool is_abm_supported; struct mall_stream_config mall_stream_config; + bool fpo_in_use; }; enum hubp_dmdata_mode { @@ -296,7 +297,6 @@ struct dc_stream_state { bool has_non_synchronizable_pclk; bool vblank_synchronized; - bool fpo_in_use; bool is_phantom; struct luminance_data lumin_data; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index 81f7b90849ce..cf908958a06b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -387,13 +387,17 @@ void dcn30_fpu_calculate_wm_and_dlg( double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][maxMpcComb]; bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] != dm_dram_clock_change_unsupported; unsigned int dummy_latency_index = 0; + struct dc_stream_status *stream_status = NULL; dc_assert_fp_enabled(); context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; for (i = 0; i < context->stream_count; i++) { + stream_status = NULL; if (context->streams[i]) - context->streams[i]->fpo_in_use = false; + stream_status = dc_state_get_stream_status(context, context->streams[i]); + if (stream_status) + stream_status->fpo_in_use = false; } if (!pstate_en) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 7aba7112c8f8..194422dd979d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2309,6 +2309,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, bool need_fclk_lat_as_dummy = false; bool is_subvp_p_drr = false; struct dc_stream_state *fpo_candidate_stream = NULL; + struct dc_stream_status *stream_status = NULL; dc_assert_fp_enabled(); @@ -2343,8 +2344,11 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; for (i = 0; i < context->stream_count; i++) { + stream_status = NULL; if (context->streams[i]) - context->streams[i]->fpo_in_use = false; + stream_status = dc_state_get_stream_status(context, context->streams[i]); + if (stream_status) + stream_status->fpo_in_use = false; } if (!pstate_en || (!dc->debug.disable_fpo_optimizations && @@ -2352,7 +2356,9 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, /* only when the mclk switch can not be natural, is the fw based vblank stretch attempted */ fpo_candidate_stream = dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(dc, context); if (fpo_candidate_stream) { - fpo_candidate_stream->fpo_in_use = true; + stream_status = dc_state_get_stream_status(context, fpo_candidate_stream); + if (stream_status) + stream_status->fpo_in_use = true; context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = true; } @@ -2389,8 +2395,11 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, */ context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; for (i = 0; i < context->stream_count; i++) { + stream_status = NULL; if (context->streams[i]) - context->streams[i]->fpo_in_use = false; + stream_status = dc_state_get_stream_status(context, context->streams[i]); + if (stream_status) + stream_status->fpo_in_use = false; } context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us; dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 2626ef8f3292..25c9a407779b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -601,9 +601,13 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; struct hubp *hubp = pipe->plane_res.hubp; + struct dc_stream_status *stream_status = NULL; + + if (pipe->stream) + stream_status = dc_state_get_stream_status(context, pipe->stream); if (!pipe->stream || !(dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN || - pipe->stream->fpo_in_use)) { + (stream_status && stream_status->fpo_in_use))) { if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) hubp->funcs->hubp_update_force_pstate_disallow(hubp, false); if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) @@ -617,6 +621,8 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context) struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; struct hubp *hubp = pipe->plane_res.hubp; + struct dc_stream_status *stream_status = NULL; + struct dc_stream_status *old_stream_status = NULL; /* Today for MED update type we do not call update clocks. However, for FPO * the assumption is that update clocks should be called to disable P-State @@ -630,11 +636,15 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context) * time SubVP / FPO was enabled, so there's no need to update / reset it if the * pipe config has never exited SubVP / FPO. */ + if (pipe->stream) + stream_status = dc_state_get_stream_status(context, pipe->stream); + if (old_pipe->stream) + old_stream_status = dc_state_get_stream_status(dc->current_state, old_pipe->stream); + if (pipe->stream && (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN || - pipe->stream->fpo_in_use) && - (!old_pipe->stream || - (dc_state_get_pipe_subvp_type(context, old_pipe) != SUBVP_MAIN && - !old_pipe->stream->fpo_in_use))) { + (stream_status && stream_status->fpo_in_use)) && + (!old_pipe->stream || (dc_state_get_pipe_subvp_type(context, old_pipe) != SUBVP_MAIN && + (old_stream_status && !old_stream_status->fpo_in_use)))) { if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index 1ce727351c39..0cb2cc56d973 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -1966,6 +1966,7 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, { int refresh_rate = 0; const int minimum_refreshrate_supported = 120; + struct dc_stream_status *stream_status = NULL; if (context == NULL || context->streams[0] == NULL) return false; @@ -1999,7 +2000,12 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, if (context->streams[0]->vrr_active_variable && (dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE)) return false; - context->streams[0]->fpo_in_use = true; + stream_status = dc_state_get_stream_status(context, context->streams[0]); + + if (!stream_status) + return false; + + stream_status->fpo_in_use = true; return true; } -- 2.34.1