From: Wayne Lin <[email protected]>

[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 <[email protected]>
Signed-off-by: Wayne Lin <[email protected]>
Signed-off-by: Chuanyu Tseng <[email protected]>
---
 .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c  |  2 +-
 .../dc/resource/dcn21/dcn21_resource.c        | 30 +++++++++++--------
 .../dc/resource/dcn21/dcn21_resource.h        |  3 +-
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index 7aaf13bbd4e4..ae34982b1b1c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index e57022af2c2a..a612c8932da9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h 
b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
index a017fd9854d1..23d3a36872bb 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
@@ -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_ */
-- 
2.43.0

Reply via email to