diff options
author | Evan Quan <evan.quan@amd.com> | 2021-03-17 12:10:15 +0800 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2021-04-09 16:37:53 -0400 |
commit | 1689fca0d62aa7a685363999f9fc380c0666d955 (patch) | |
tree | cb9601ff0840e97aa558e80eb06ef399ed324dc6 /drivers/gpu/drm/amd/pm | |
parent | 50ca25228e8a0cc4eca531cdac4c9ece1e7bed68 (diff) |
drm/amd/pm: fix Navi1x runtime resume failure V2
The RLC was put into a wrong state on runtime suspend. Thus the RLC
autoload will fail on the succeeding runtime resume. By adding an
intermediate PPSMC_MSG_PrepareMp1ForUnload(some GC hard reset involved,
designed for PnP), we can bring RLC back into the desired state.
V2: integrate INTERRUPTS_ENABLED flag clearing into current
mp1 state set routines
Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Guchun Chen <guchun.chen@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/pm')
-rw-r--r-- | drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 3 |
8 files changed, 96 insertions, 24 deletions
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 25d5f03aaa67..2edb634bc1c6 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -807,6 +807,13 @@ struct pptable_funcs { int (*check_fw_status)(struct smu_context *smu); /** + * @set_mp1_state: put SMU into a correct state for comming + * resume from runpm or gpu reset. + */ + int (*set_mp1_state)(struct smu_context *smu, + enum pp_mp1_state mp1_state); + + /** * @setup_pptable: Initialize the power play table and populate it with * default values. */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 143e3783251e..05f00900d10c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1908,36 +1908,16 @@ int smu_set_mp1_state(void *handle, enum pp_mp1_state mp1_state) { struct smu_context *smu = handle; - uint16_t msg; - int ret; + int ret = 0; if (!smu->pm_enabled) return -EOPNOTSUPP; mutex_lock(&smu->mutex); - switch (mp1_state) { - case PP_MP1_STATE_SHUTDOWN: - msg = SMU_MSG_PrepareMp1ForShutdown; - break; - case PP_MP1_STATE_UNLOAD: - msg = SMU_MSG_PrepareMp1ForUnload; - break; - case PP_MP1_STATE_RESET: - msg = SMU_MSG_PrepareMp1ForReset; - break; - case PP_MP1_STATE_NONE: - default: - mutex_unlock(&smu->mutex); - return 0; - } - - ret = smu_send_smc_msg(smu, msg, NULL); - /* some asics may not support those messages */ - if (ret == -EINVAL) - ret = 0; - if (ret) - dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); + if (smu->ppt_funcs && + smu->ppt_funcs->set_mp1_state) + ret = smu->ppt_funcs->set_mp1_state(smu, mp1_state); mutex_unlock(&smu->mutex); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index bbc03092b0a9..77693bf0840c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2365,6 +2365,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_fan_parameters = arcturus_get_fan_parameters, .interrupt_work = smu_v11_0_interrupt_work, .set_light_sbr = smu_v11_0_set_light_sbr, + .set_mp1_state = smu_cmn_set_mp1_state, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 3d0de2c958fa..f827096dc849 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -431,6 +431,30 @@ static int navi10_store_powerplay_table(struct smu_context *smu) return 0; } +static int navi10_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t mp1_fw_flags; + int ret = 0; + + ret = smu_cmn_set_mp1_state(smu, mp1_state); + if (ret) + return ret; + + if (mp1_state == PP_MP1_STATE_UNLOAD) { + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + + mp1_fw_flags &= ~MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK; + + WREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff), mp1_fw_flags); + } + + return 0; +} + static int navi10_setup_pptable(struct smu_context *smu) { int ret = 0; @@ -3031,6 +3055,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_fan_parameters = navi10_get_fan_parameters, .post_init = navi10_post_smu_init, .interrupt_work = smu_v11_0_interrupt_work, + .set_mp1_state = navi10_set_mp1_state, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 3621884c3293..722fe067ac2c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3110,6 +3110,19 @@ static int sienna_cichlid_system_features_control(struct smu_context *smu, return smu_v11_0_system_features_control(smu, en); } +static int sienna_cichlid_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + switch (mp1_state) { + case PP_MP1_STATE_UNLOAD: + return smu_cmn_set_mp1_state(smu, mp1_state); + default: + return -EINVAL; + } + + return 0; +} + static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, @@ -3195,6 +3208,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_fan_parameters = sienna_cichlid_get_fan_parameters, .interrupt_work = smu_v11_0_interrupt_work, .gpo_control = sienna_cichlid_gpo_control, + .set_mp1_state = sienna_cichlid_set_mp1_state, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 9813a86ca31a..7d38b92a78dc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1460,6 +1460,19 @@ static bool aldebaran_is_mode2_reset_supported(struct smu_context *smu) return true; } +static int aldebaran_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + switch (mp1_state) { + case PP_MP1_STATE_UNLOAD: + return smu_cmn_set_mp1_state(smu, mp1_state); + default: + return -EINVAL; + } + + return 0; +} + static const struct pptable_funcs aldebaran_ppt_funcs = { /* init dpm */ .get_allowed_feature_mask = aldebaran_get_allowed_feature_mask, @@ -1518,6 +1531,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = { .mode2_reset_is_support = aldebaran_is_mode2_reset_supported, .mode1_reset = smu_v13_0_mode1_reset, .mode2_reset = smu_v13_0_mode2_reset, + .set_mp1_state = aldebaran_set_mp1_state, }; void aldebaran_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 4b45953b36d8..2d216f5b167d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -780,3 +780,31 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) header->structure_size = structure_size; } + +int smu_cmn_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + enum smu_message_type msg; + int ret; + + switch (mp1_state) { + case PP_MP1_STATE_SHUTDOWN: + msg = SMU_MSG_PrepareMp1ForShutdown; + break; + case PP_MP1_STATE_UNLOAD: + msg = SMU_MSG_PrepareMp1ForUnload; + break; + case PP_MP1_STATE_RESET: + msg = SMU_MSG_PrepareMp1ForReset; + break; + case PP_MP1_STATE_NONE: + default: + return 0; + } + + ret = smu_cmn_send_smc_msg(smu, msg, NULL); + if (ret) + dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index c69250185575..155e2a68fa1c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -99,5 +99,8 @@ int smu_cmn_get_metrics_table(struct smu_context *smu, void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev); +int smu_cmn_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state); + #endif #endif |