On SOCs with SMU v13.0.6, allow changing xgmi plpd policy through pm_policy sysfs interface. Signed-off-by: Lijo Lazar <lijo.lazar@xxxxxxx> Reviewed-by: Hawking Zhang <Hawking.Zhang@xxxxxxx> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 +++++- .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 51 +++++++++++++++++-- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 27 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 1 + 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 1c23e0985377..42d43da7de4c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1190,6 +1190,9 @@ static void smu_swctf_delayed_work_handler(struct work_struct *work) static void smu_init_xgmi_plpd_mode(struct smu_context *smu) { + struct smu_dpm_context *dpm_ctxt = &(smu->smu_dpm); + struct smu_dpm_policy_ctxt *policy_ctxt; + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 2)) { smu->plpd_mode = XGMI_PLPD_DEFAULT; return; @@ -1197,10 +1200,18 @@ static void smu_init_xgmi_plpd_mode(struct smu_context *smu) /* PMFW put PLPD into default policy after enabling the feature */ if (smu_feature_is_enabled(smu, - SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT)) + SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT)) { + struct smu_dpm_policy *policy; + smu->plpd_mode = XGMI_PLPD_DEFAULT; - else + policy = smu_get_pm_policy(smu, PP_PM_POLICY_XGMI_PLPD); + if (policy) + policy->current_level = XGMI_PLPD_DEFAULT; + } else { smu->plpd_mode = XGMI_PLPD_NONE; + policy_ctxt = dpm_ctxt->dpm_policies; + policy_ctxt->policy_mask &= ~BIT(PP_PM_POLICY_XGMI_PLPD); + } } static int smu_sw_init(void *handle) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index f227f05100f8..2d6428ca1217 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -402,9 +402,45 @@ static int smu_v13_0_6_select_policy_soc_pstate(struct smu_context *smu, return ret; } +static int smu_v13_0_6_select_plpd_policy(struct smu_context *smu, int level) +{ + struct amdgpu_device *adev = smu->adev; + int ret, param; + + switch (level) { + case XGMI_PLPD_DEFAULT: + param = PPSMC_PLPD_MODE_DEFAULT; + break; + case XGMI_PLPD_OPTIMIZED: + param = PPSMC_PLPD_MODE_OPTIMIZED; + break; + case XGMI_PLPD_DISALLOW: + param = 0; + break; + default: + return -EINVAL; + } + + if (level == XGMI_PLPD_DISALLOW) + ret = smu_cmn_send_smc_msg_with_param( + smu, SMU_MSG_GmiPwrDnControl, param, NULL); + else + /* change xgmi per-link power down policy */ + ret = smu_cmn_send_smc_msg_with_param( + smu, SMU_MSG_SelectPLPDMode, param, NULL); + + if (ret) + dev_err(adev->dev, + "select xgmi per-link power down policy %d failed\n", + level); + + return ret; +} + static int smu_v13_0_6_allocate_dpm_context(struct smu_context *smu) { struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_dpm_policy *policy; smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context), GFP_KERNEL); @@ -412,11 +448,9 @@ static int smu_v13_0_6_allocate_dpm_context(struct smu_context *smu) return -ENOMEM; smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context); + smu_dpm->dpm_policies = + kzalloc(sizeof(struct smu_dpm_policy_ctxt), GFP_KERNEL); if (!(smu->adev->flags & AMD_IS_APU)) { - struct smu_dpm_policy *policy; - - smu_dpm->dpm_policies = - kzalloc(sizeof(struct smu_dpm_policy_ctxt), GFP_KERNEL); policy = &(smu_dpm->dpm_policies->policies[0]); policy->policy_type = PP_PM_POLICY_SOC_PSTATE; @@ -429,6 +463,15 @@ static int smu_v13_0_6_allocate_dpm_context(struct smu_context *smu) smu_dpm->dpm_policies->policy_mask |= BIT(PP_PM_POLICY_SOC_PSTATE); } + policy = &(smu_dpm->dpm_policies->policies[1]); + + policy->policy_type = PP_PM_POLICY_XGMI_PLPD; + policy->level_mask = BIT(XGMI_PLPD_DISALLOW) | BIT(XGMI_PLPD_DEFAULT) | + BIT(XGMI_PLPD_OPTIMIZED); + policy->current_level = XGMI_PLPD_DEFAULT; + policy->set_policy = smu_v13_0_6_select_plpd_policy; + smu_cmn_generic_plpd_policy_desc(policy); + smu_dpm->dpm_policies->policy_mask |= BIT(PP_PM_POLICY_XGMI_PLPD); return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index ce14d94b9650..7b5bcec583bc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -1109,3 +1109,30 @@ void smu_cmn_generic_soc_policy_desc(struct smu_dpm_policy *policy) policy->desc = &pstate_policy_desc; } +static char *smu_xgmi_plpd_policy_get_desc(struct smu_dpm_policy *policy, + int level) +{ + if (level < 0 || !(policy->level_mask & BIT(level))) + return "Invalid"; + + switch (level) { + case XGMI_PLPD_DISALLOW: + return "plpd_disallow"; + case XGMI_PLPD_DEFAULT: + return "plpd_default"; + case XGMI_PLPD_OPTIMIZED: + return "plpd_optimized"; + } + + return "Invalid"; +} + +static struct smu_dpm_policy_desc xgmi_plpd_policy_desc = { + .name = "xgmi plpd", + .get_desc = smu_xgmi_plpd_policy_get_desc, +}; + +void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy) +{ + policy->desc = &xgmi_plpd_policy_desc; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index d135d984329e..1de685defe85 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -145,6 +145,7 @@ static inline void smu_cmn_get_sysfs_buf(char **buf, int *offset) bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev); void smu_cmn_generic_soc_policy_desc(struct smu_dpm_policy *policy); +void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy); #endif #endif -- 2.25.1