Commit 46ddb896 authored by Eric Yang's avatar Eric Yang Committed by Alex Deucher

drm/amd/display: implement workaround for riommu related hang

[Why]
During S4/S5/reboot, sometimes riommu invalidation request arrive too
early, DCN may be unable to respond to the invalidation request
resulting in pstate hang.

[How]
VBIOS will force allow pstate for riommu invalidation and driver will
clear it after powering down display pipes.
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarEric Yang <Eric.Yang2@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 98e95e4f
...@@ -636,6 +636,7 @@ struct dce_hwseq_registers { ...@@ -636,6 +636,7 @@ struct dce_hwseq_registers {
uint32_t ODM_MEM_PWR_CTRL3; uint32_t ODM_MEM_PWR_CTRL3;
uint32_t DMU_MEM_PWR_CNTL; uint32_t DMU_MEM_PWR_CNTL;
uint32_t MMHUBBUB_MEM_PWR_CNTL; uint32_t MMHUBBUB_MEM_PWR_CNTL;
uint32_t DCHUBBUB_ARB_HOSTVM_CNTL;
}; };
/* set field name */ /* set field name */
#define HWS_SF(blk_name, reg_name, field_name, post_fix)\ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\
...@@ -1110,7 +1111,8 @@ struct dce_hwseq_registers { ...@@ -1110,7 +1111,8 @@ struct dce_hwseq_registers {
type DOMAIN_POWER_FORCEON;\ type DOMAIN_POWER_FORCEON;\
type DOMAIN_POWER_GATE;\ type DOMAIN_POWER_GATE;\
type DOMAIN_PGFSM_PWR_STATUS;\ type DOMAIN_PGFSM_PWR_STATUS;\
type HPO_HDMISTREAMCLK_G_GATE_DIS; type HPO_HDMISTREAMCLK_G_GATE_DIS;\
type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;
struct dce_hwseq_shift { struct dce_hwseq_shift {
HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_REG_FIELD_LIST(uint8_t)
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "dce/dmub_outbox.h" #include "dce/dmub_outbox.h"
#include "dc_link_dp.h" #include "dc_link_dp.h"
#include "inc/link_dpcd.h" #include "inc/link_dpcd.h"
#include "dcn10/dcn10_hw_sequencer.h"
#define DC_LOGGER_INIT(logger) #define DC_LOGGER_INIT(logger)
...@@ -594,3 +595,20 @@ bool dcn31_is_abm_supported(struct dc *dc, ...@@ -594,3 +595,20 @@ bool dcn31_is_abm_supported(struct dc *dc,
} }
return false; return false;
} }
static void apply_riommu_invalidation_wa(struct dc *dc)
{
struct dce_hwseq *hws = dc->hwseq;
if (!hws->wa.early_riommu_invalidation)
return;
REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, 0);
}
void dcn31_init_pipes(struct dc *dc, struct dc_state *context)
{
dcn10_init_pipes(dc, context);
apply_riommu_invalidation_wa(dc);
}
...@@ -52,5 +52,6 @@ void dcn31_reset_hw_ctx_wrap( ...@@ -52,5 +52,6 @@ void dcn31_reset_hw_ctx_wrap(
struct dc_state *context); struct dc_state *context);
bool dcn31_is_abm_supported(struct dc *dc, bool dcn31_is_abm_supported(struct dc *dc,
struct dc_state *context, struct dc_stream_state *stream); struct dc_state *context, struct dc_stream_state *stream);
void dcn31_init_pipes(struct dc *dc, struct dc_state *context);
#endif /* __DC_HWSS_DCN31_H__ */ #endif /* __DC_HWSS_DCN31_H__ */
...@@ -104,7 +104,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { ...@@ -104,7 +104,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
}; };
static const struct hwseq_private_funcs dcn31_private_funcs = { static const struct hwseq_private_funcs dcn31_private_funcs = {
.init_pipes = dcn10_init_pipes, .init_pipes = dcn31_init_pipes,
.update_plane_addr = dcn20_update_plane_addr, .update_plane_addr = dcn20_update_plane_addr,
.plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
.update_mpcc = dcn20_update_mpcc, .update_mpcc = dcn20_update_mpcc,
......
...@@ -741,6 +741,7 @@ static const struct dccg_mask dccg_mask = { ...@@ -741,6 +741,7 @@ static const struct dccg_mask dccg_mask = {
#define HWSEQ_DCN31_REG_LIST()\ #define HWSEQ_DCN31_REG_LIST()\
SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
SR(DCHUBBUB_ARB_HOSTVM_CNTL), \
SR(DIO_MEM_PWR_CTRL), \ SR(DIO_MEM_PWR_CTRL), \
SR(ODM_MEM_PWR_CTRL3), \ SR(ODM_MEM_PWR_CTRL3), \
SR(DMU_MEM_PWR_CNTL), \ SR(DMU_MEM_PWR_CNTL), \
...@@ -801,6 +802,7 @@ static const struct dce_hwseq_registers hwseq_reg = { ...@@ -801,6 +802,7 @@ static const struct dce_hwseq_registers hwseq_reg = {
#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\
HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
...@@ -1299,6 +1301,7 @@ static struct dce_hwseq *dcn31_hwseq_create( ...@@ -1299,6 +1301,7 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg; hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift; hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask; hws->masks = &hwseq_mask;
hws->wa.early_riommu_invalidation = true;
} }
return hws; return hws;
} }
......
...@@ -41,6 +41,7 @@ struct dce_hwseq_wa { ...@@ -41,6 +41,7 @@ struct dce_hwseq_wa {
bool DEGVIDCN10_254; bool DEGVIDCN10_254;
bool DEGVIDCN21; bool DEGVIDCN21;
bool disallow_self_refresh_during_multi_plane_transition; bool disallow_self_refresh_during_multi_plane_transition;
bool early_riommu_invalidation;
}; };
struct hwseq_wa_state { struct hwseq_wa_state {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment