]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Should support p-state under dcn21
authorWayne Lin <Wayne.Lin@amd.com>
Thu, 5 Feb 2026 07:36:18 +0000 (15:36 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 30 Mar 2026 18:39:36 +0000 (14:39 -0400)
[Why]
Under DCN21, observe flip_done timeout issue while
running 3D benchmark under MPO case. Timeout is caused
by driver fails validate_bandwidth() during
atomic_commit_tail but passes atomic_check.

Under further analysis, indicates the delta of
atomic_check and atomic_commit_tail are
dc->current_state->bw_ctx.dml.soc.sr_exit_time_us and
dc->current_state->bw_ctx.dml.soc.sr_enter_plus_exit_time_us.

We set validate_mode as DC_VALIDATE_MODE_ONLY while calling
dc_validate_global_state() at atomic_check, but set mode as
DC_VALIDATE_MODE_AND_PROGRAMMING during atomic_commit_tail.
If dc_validate_mode set as DC_VALIDATE_MODE_ONLY,
validate_bandwidth() will skip the wm and dlg calculation.

During commit_tail, validate_bandwidth() is called with
dc_validate_mode set as DC_VALIDATE_MODE_AND_PROGRAMMING and
dc_state->bw_ctx.dml.soc.sr_exit_time_us might get modified
after the wm_calculation and stored into dc->current_state.
Which means dc->current_state->bw_ctx.dml.soc.sr_exit_time_us
might not aligned with the one stored in dm_state->context.
That causes duplicated dm_state->context not aligned with
dc->current_state, and might have bandwidth validation pass
in atomic_check and fail in commit_tail later.

[How]
When the issue occurs, it fails dml_get_voltage_level() with
the condition dm_allow_self_refresh_and_mclk_switch but pass
with the condition dm_allow_self_refresh. However, we should
support p-state. So we should not pass validate_bandwidth by
allowing self refresh only. Change the policy under DCN21.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: Chuanyu Tseng <chuanyu.tseng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h

index 7aaf13bbd4e4c1d068051c7275e574f8f48c768d..ae34982b1b1c09bb23a750a53e28d2af27e68f54 100644 (file)
@@ -2335,7 +2335,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
        /*Unsafe due to current pipe merge and split logic*/
        ASSERT(context != dc->current_state);
 
-       out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode);
+       out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode, false);
 
        if (pipe_cnt == 0)
                goto validate_out;
index a1a529cabb93041a2c2b6aa12da012133cb4846d..f7f75604ef338eef7987b32576f63b3db0032e5b 100644 (file)
@@ -772,7 +772,8 @@ bool dcn21_fast_validate_bw(struct dc *dc,
                            int *pipe_cnt_out,
                            int *pipe_split_from,
                            int *vlevel_out,
-                           enum dc_validate_mode validate_mode)
+                           enum dc_validate_mode validate_mode,
+                           bool allow_self_refresh_only)
 {
        bool out = false;
        int split[MAX_PIPES] = { 0 };
@@ -803,18 +804,23 @@ bool dcn21_fast_validate_bw(struct dc *dc,
        vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
 
        if (vlevel > context->bw_ctx.dml.soc.num_states) {
-               /*
-                * If mode is unsupported or there's still no p-state support then
-                * fall back to favoring voltage.
-                *
-                * We don't actually support prefetch mode 2, so require that we
-                * at least support prefetch mode 1.
-                */
-               context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
-                                       dm_allow_self_refresh;
-               vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
-               if (vlevel > context->bw_ctx.dml.soc.num_states)
+
+               if (allow_self_refresh_only) {
+                       /*
+                        * If mode is unsupported or there's still no p-state support then
+                        * fall back to favoring voltage.
+                        *
+                        * We don't actually support prefetch mode 2, so require that we
+                        * at least support prefetch mode 1.
+                        */
+                       context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
+                                               dm_allow_self_refresh;
+                       vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+                       if (vlevel > context->bw_ctx.dml.soc.num_states)
+                               goto validate_fail;
+               } else {
                        goto validate_fail;
+               }
        }
 
        vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
index a017fd9854d14cfd5cdbb34ba9bd752a7d677b12..23d3a36872bb44edbcad43cbe8c37b5dfaa5e4a2 100644 (file)
@@ -51,6 +51,7 @@ bool dcn21_fast_validate_bw(
                int *pipe_cnt_out,
                int *pipe_split_from,
                int *vlevel_out,
-               enum dc_validate_mode validate_mode);
+               enum dc_validate_mode validate_mode,
+               bool allow_self_refresh_only);
 
 #endif /* _DCN21_RESOURCE_H_ */