drm/amd/display: Wait DMCUB to idle state before reset.
authorhengzhou <Hengyong.Zhou@amd.com>
Sat, 7 May 2022 01:43:08 +0000 (09:43 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jun 2022 19:56:48 +0000 (15:56 -0400)
[WHY]
Very low rate to cause memory access issue while resetting
DMCUB after the halt command was sent to it.
The process of stopping fw of DMCUB may be timeout, that means
it is not in idle state, such as the window frames may still be
kept in cache, so reset by force will cause MMHUB hang.

[HOW]
After the halt command was sent, keep checking the DMCUB state until
it is idle.

Reviewed-by: Eric Yang <Eric.Yang2@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Jasdeep Dhillon <jdhillon@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: hengzhou <Hengyong.Zhou@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h

index 4c880b64f8ca1c2792746075a1603e1b5e5867c4..c7021915bac8815d1c3182ceed1e17887888642e 100644 (file)
@@ -62,7 +62,7 @@ struct dccg {
        int ref_dppclk;
        //int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */
        //int audio_dtbclk_khz;/* TODO needs to be removed */
-       //int ref_dtbclk_khz;/* TODO needs to be removed */
+       int ref_dtbclk_khz;/* TODO needs to be removed */
 };
 
 struct dtbclk_dto_params {
index 7c9330a61ac1bcc7becb636aa746445a60dc6f80..8d4574895757675d6d6368cd32250e5439d9c6a5 100644 (file)
@@ -84,7 +84,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
 {
        union dmub_gpint_data_register cmd;
        const uint32_t timeout = 100;
-       uint32_t in_reset, scratch, i;
+       uint32_t in_reset, scratch, i, pwait_mode;
 
        REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
 
@@ -115,6 +115,13 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
                        udelay(1);
                }
 
+               for (i = 0; i < timeout; ++i) {
+                       REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode);
+                       if (pwait_mode & (1 << 0))
+                               break;
+
+                       udelay(1);
+               }
                /* Force reset in case we timed out, DMCUB is likely hung. */
        }
 
index 59ddc81b5a0e4756c2b4d202d1e05fa54764ecee..f6db6f89d45dc74b6c17a6c506c53a8a0df5ed00 100644 (file)
@@ -151,7 +151,8 @@ struct dmub_srv;
        DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
        DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
        DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
-       DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK)
+       DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) \
+       DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS)
 
 struct dmub_srv_dcn31_reg_offset {
 #define DMUB_SR(reg) uint32_t reg;