[PATCH 06/18] drm/amd/display: Force enable pstate on driver unload

Eryk Brol eryk.brol at amd.com
Sun Oct 4 17:18:01 UTC 2020


From: Joshua Aberback <joshua.aberback at amd.com>

[Why]
During driver unload, it is expected that p-state switching is supported.
If it's not supported, PMFW will hang due to a forced p-state switch. Even
if the current timing does not support p-state normally, we still want to
force allow because the worst that can happen is underflow. This will
match Navi10 behaviour.

[How]
 - new hubbub func to control the force pstate register
 - force allow when releasing display ownership
   - registers are inaccessible after due to m_cgs.hwNotAvailable
 - explicitly disable force signal during hw_init
   - if driver is disabled and re-enabled, register not cleared otherwise

Also, remove DCN3 part of dcn10_init_hw, we will not be going back to it.

Signed-off-by: Joshua Aberback <joshua.aberback at amd.com>
Reviewed-by: Jun Lei <Jun.Lei at amd.com>
Acked-by: Eryk Brol <eryk.brol at amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c            |  7 +++++++
 drivers/gpu/drm/amd/display/dc/dc.h                 |  3 +++
 .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c   |  6 ------
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c | 11 +++++++++++
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h |  3 +++
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c  | 13 +++++++++++++
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h  |  2 ++
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c   |  1 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h    |  4 ++++
 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h   |  3 +++
 10 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 014d7571474e..8d96ef157987 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3097,4 +3097,11 @@ bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc,
 {
 	return false;
 }
+
+/* cleanup on driver unload */
+void dc_hardware_release(struct dc *dc)
+{
+	if (dc->hwss.hardware_release)
+		dc->hwss.hardware_release(dc);
+}
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 3ea4be40050d..d893211977ff 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1267,6 +1267,9 @@ void dc_unlock_memory_clock_frequency(struct dc *dc);
  */
 void dc_lock_memory_clock_frequency(struct dc *dc);
 
+/* cleanup on driver unload */
+void dc_hardware_release(struct dc *dc);
+
 #endif
 
 bool dc_set_psr_allow_active(struct dc *dc, bool enable);
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 256185a22800..86a0d46ff2e4 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
@@ -1434,12 +1434,6 @@ void dcn10_init_hw(struct dc *dc)
 
 	if (dc->clk_mgr->funcs->notify_wm_ranges)
 		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
-
-#ifdef CONFIG_DRM_AMD_DC_DCN3_0
-	if (dc->clk_mgr->funcs->set_hard_max_memclk)
-		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
-#endif
-
 }
 
 /* In headless boot cases, DIG may be turned
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 982732dec133..2c68a246fa83 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
@@ -384,6 +384,16 @@ void hubbub3_force_wm_propagate_to_pipes(struct hubbub *hubbub)
 			DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);
 }
 
+void hubbub3_force_pstate_change_control(struct hubbub *hubbub,
+		bool force, bool allow)
+{
+	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+
+	REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+			DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, allow,
+			DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, force);
+}
+
 static const struct hubbub_funcs hubbub30_funcs = {
 	.update_dchub = hubbub2_update_dchub,
 	.init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
@@ -397,6 +407,7 @@ static const struct hubbub_funcs hubbub30_funcs = {
 	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
 	.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
 	.force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
+	.force_pstate_change_control = hubbub3_force_pstate_change_control,
 };
 
 void hubbub3_construct(struct dcn20_hubbub *hubbub3,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
index 790baa00672b..38f1d2fd939b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
@@ -116,4 +116,7 @@ bool hubbub3_program_watermarks(
 		unsigned int refclk_mhz,
 		bool safe_to_lower);
 
+void hubbub3_force_pstate_change_control(struct hubbub *hubbub,
+		bool force, bool allow);
+
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index 204773ffc376..2ace13878aaf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -622,6 +622,10 @@ void dcn30_init_hw(struct dc *dc)
 
 	if (dc->clk_mgr->funcs->set_hard_max_memclk)
 		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
+
+	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+		dc->res_pool->hubbub->funcs->force_pstate_change_control(
+				dc->res_pool->hubbub, false, false);
 }
 
 void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
@@ -711,3 +715,12 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
 
 	return true;
 }
+
+void dcn30_hardware_release(struct dc *dc)
+{
+	/* if pstate unsupported, force it supported */
+	if (!dc->clk_mgr->clks.p_state_change_support &&
+			dc->res_pool->hubbub->funcs->force_pstate_change_control)
+		dc->res_pool->hubbub->funcs->force_pstate_change_control(
+				dc->res_pool->hubbub, true, true);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
index a4989f5ac4e9..0ae047221afe 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
@@ -67,4 +67,6 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx);
 
 bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable);
 
+void dcn30_hardware_release(struct dc *dc);
+
 #endif /* __DC_HWSS_DCN30_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
index 7c90c2222506..ae7a789bf6e6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
@@ -93,6 +93,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
 	.apply_idle_power_optimizations = dcn30_apply_idle_power_optimizations,
 	.set_backlight_level = dcn21_set_backlight_level,
 	.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
+	.hardware_release = dcn30_hardware_release,
 };
 
 static const struct hwseq_private_funcs dcn30_private_funcs = {
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 65f182c8bf14..371da657c8a4 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -152,6 +152,10 @@ struct hubbub_funcs {
 	void (*apply_DEDCN21_147_wa)(struct hubbub *hubbub);
 
 	void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub);
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+
+	void (*force_pstate_change_control)(struct hubbub *hubbub, bool force, bool allow);
+#endif
 };
 
 struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index f48ee24d42f9..55c642950e91 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -50,6 +50,9 @@ struct dpp;
 struct dce_hwseq;
 
 struct hw_sequencer_funcs {
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+	void (*hardware_release)(struct dc *dc);
+#endif
 	/* Embedded Display Related */
 	void (*edp_power_control)(struct dc_link *link, bool enable);
 	void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up);
-- 
2.25.1



More information about the amd-gfx mailing list