Commit 1689fca0 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher

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: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Reviewed-by: default avatarGuchun Chen <guchun.chen@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 50ca2522
...@@ -2146,9 +2146,12 @@ static int psp_load_smu_fw(struct psp_context *psp) ...@@ -2146,9 +2146,12 @@ static int psp_load_smu_fw(struct psp_context *psp)
if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
return 0; return 0;
if ((amdgpu_in_reset(adev) &&
if (amdgpu_in_reset(adev) && ras && ras->supported && ras && ras->supported &&
adev->asic_type == CHIP_ARCTURUS) { adev->asic_type == CHIP_ARCTURUS) ||
(adev->in_runpm &&
adev->asic_type >= CHIP_NAVI10 &&
adev->asic_type <= CHIP_NAVI12)) {
ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
if (ret) { if (ret) {
DRM_WARN("Failed to set MP1 state prepare for reload\n"); DRM_WARN("Failed to set MP1 state prepare for reload\n");
......
...@@ -806,6 +806,13 @@ struct pptable_funcs { ...@@ -806,6 +806,13 @@ struct pptable_funcs {
*/ */
int (*check_fw_status)(struct smu_context *smu); 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 * @setup_pptable: Initialize the power play table and populate it with
* default values. * default values.
......
...@@ -1908,36 +1908,16 @@ int smu_set_mp1_state(void *handle, ...@@ -1908,36 +1908,16 @@ int smu_set_mp1_state(void *handle,
enum pp_mp1_state mp1_state) enum pp_mp1_state mp1_state)
{ {
struct smu_context *smu = handle; struct smu_context *smu = handle;
uint16_t msg; int ret = 0;
int ret;
if (!smu->pm_enabled) if (!smu->pm_enabled)
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&smu->mutex); mutex_lock(&smu->mutex);
switch (mp1_state) { if (smu->ppt_funcs &&
case PP_MP1_STATE_SHUTDOWN: smu->ppt_funcs->set_mp1_state)
msg = SMU_MSG_PrepareMp1ForShutdown; ret = smu->ppt_funcs->set_mp1_state(smu, mp1_state);
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");
mutex_unlock(&smu->mutex); mutex_unlock(&smu->mutex);
......
...@@ -2365,6 +2365,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { ...@@ -2365,6 +2365,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
.get_fan_parameters = arcturus_get_fan_parameters, .get_fan_parameters = arcturus_get_fan_parameters,
.interrupt_work = smu_v11_0_interrupt_work, .interrupt_work = smu_v11_0_interrupt_work,
.set_light_sbr = smu_v11_0_set_light_sbr, .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) void arcturus_set_ppt_funcs(struct smu_context *smu)
......
...@@ -431,6 +431,30 @@ static int navi10_store_powerplay_table(struct smu_context *smu) ...@@ -431,6 +431,30 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
return 0; 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) static int navi10_setup_pptable(struct smu_context *smu)
{ {
int ret = 0; int ret = 0;
...@@ -3031,6 +3055,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { ...@@ -3031,6 +3055,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.get_fan_parameters = navi10_get_fan_parameters, .get_fan_parameters = navi10_get_fan_parameters,
.post_init = navi10_post_smu_init, .post_init = navi10_post_smu_init,
.interrupt_work = smu_v11_0_interrupt_work, .interrupt_work = smu_v11_0_interrupt_work,
.set_mp1_state = navi10_set_mp1_state,
}; };
void navi10_set_ppt_funcs(struct smu_context *smu) void navi10_set_ppt_funcs(struct smu_context *smu)
......
...@@ -3110,6 +3110,19 @@ static int sienna_cichlid_system_features_control(struct smu_context *smu, ...@@ -3110,6 +3110,19 @@ static int sienna_cichlid_system_features_control(struct smu_context *smu,
return smu_v11_0_system_features_control(smu, en); 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 = { static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask,
.set_default_dpm_table = sienna_cichlid_set_default_dpm_table, .set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
...@@ -3195,6 +3208,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { ...@@ -3195,6 +3208,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.get_fan_parameters = sienna_cichlid_get_fan_parameters, .get_fan_parameters = sienna_cichlid_get_fan_parameters,
.interrupt_work = smu_v11_0_interrupt_work, .interrupt_work = smu_v11_0_interrupt_work,
.gpo_control = sienna_cichlid_gpo_control, .gpo_control = sienna_cichlid_gpo_control,
.set_mp1_state = sienna_cichlid_set_mp1_state,
}; };
void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) void sienna_cichlid_set_ppt_funcs(struct smu_context *smu)
......
...@@ -1460,6 +1460,19 @@ static bool aldebaran_is_mode2_reset_supported(struct smu_context *smu) ...@@ -1460,6 +1460,19 @@ static bool aldebaran_is_mode2_reset_supported(struct smu_context *smu)
return true; 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 = { static const struct pptable_funcs aldebaran_ppt_funcs = {
/* init dpm */ /* init dpm */
.get_allowed_feature_mask = aldebaran_get_allowed_feature_mask, .get_allowed_feature_mask = aldebaran_get_allowed_feature_mask,
...@@ -1518,6 +1531,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = { ...@@ -1518,6 +1531,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
.mode2_reset_is_support = aldebaran_is_mode2_reset_supported, .mode2_reset_is_support = aldebaran_is_mode2_reset_supported,
.mode1_reset = smu_v13_0_mode1_reset, .mode1_reset = smu_v13_0_mode1_reset,
.mode2_reset = smu_v13_0_mode2_reset, .mode2_reset = smu_v13_0_mode2_reset,
.set_mp1_state = aldebaran_set_mp1_state,
}; };
void aldebaran_set_ppt_funcs(struct smu_context *smu) void aldebaran_set_ppt_funcs(struct smu_context *smu)
......
...@@ -780,3 +780,31 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) ...@@ -780,3 +780,31 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
header->structure_size = structure_size; 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;
}
...@@ -99,5 +99,8 @@ int smu_cmn_get_metrics_table(struct smu_context *smu, ...@@ -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); 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
#endif #endif
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