From 5632708f4452eb9afb985b245b98dac9a5feeac2 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 12 Apr 2016 14:57:23 -0400 Subject: [PATCH] drm/amd/powerplay: add dpm force multiple levels on cz/tonga/fiji/polaris (v2) Allows you to force multiple levels rather than just one via the new sysfs interrface. v2: squash in: drm/amd/powerplay: ensure clock level set by user is valid. From Rex. Reviewed-by: Alex Deucher Signed-off-by: Eric Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 51 +++++++++++++------ drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 4 +- .../gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 6 +-- .../gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c | 18 +++++-- .../drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 16 ++++-- .../gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 16 ++++-- .../gpu/drm/amd/powerplay/inc/amd_powerplay.h | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 +- 8 files changed, 81 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 6d44d4a64698..589b36e8c5cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -362,16 +362,23 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret; long level; + uint32_t i, mask = 0; + char sub_str[2]; - ret = kstrtol(buf, 0, &level); + for (i = 0; i < strlen(buf) - 1; i++) { + sub_str[0] = *(buf + i); + sub_str[1] = '\0'; + ret = kstrtol(sub_str, 0, &level); - if (ret) { - count = -EINVAL; - goto fail; + if (ret) { + count = -EINVAL; + goto fail; + } + mask |= 1 << level; } if (adev->pp_enabled) - amdgpu_dpm_force_clock_level(adev, PP_SCLK, level); + amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); fail: return count; } @@ -399,16 +406,23 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret; long level; + uint32_t i, mask = 0; + char sub_str[2]; - ret = kstrtol(buf, 0, &level); + for (i = 0; i < strlen(buf) - 1; i++) { + sub_str[0] = *(buf + i); + sub_str[1] = '\0'; + ret = kstrtol(sub_str, 0, &level); - if (ret) { - count = -EINVAL; - goto fail; + if (ret) { + count = -EINVAL; + goto fail; + } + mask |= 1 << level; } if (adev->pp_enabled) - amdgpu_dpm_force_clock_level(adev, PP_MCLK, level); + amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); fail: return count; } @@ -436,16 +450,23 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret; long level; + uint32_t i, mask = 0; + char sub_str[2]; - ret = kstrtol(buf, 0, &level); + for (i = 0; i < strlen(buf) - 1; i++) { + sub_str[0] = *(buf + i); + sub_str[1] = '\0'; + ret = kstrtol(sub_str, 0, &level); - if (ret) { - count = -EINVAL; - goto fail; + if (ret) { + count = -EINVAL; + goto fail; + } + mask |= 1 << level; } if (adev->pp_enabled) - amdgpu_dpm_force_clock_level(adev, PP_PCIE, level); + amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); fail: return count; } diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index ce8d9bf8d68d..0527ae3d10f9 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -763,7 +763,7 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) } static int pp_dpm_force_clock_level(void *handle, - enum pp_clock_type type, int level) + enum pp_clock_type type, uint32_t mask) { struct pp_hwmgr *hwmgr; @@ -779,7 +779,7 @@ static int pp_dpm_force_clock_level(void *handle, return 0; } - return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, level); + return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); } static int pp_dpm_print_clock_levels(void *handle, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 648394fff69a..1f14c477d15d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1729,7 +1729,7 @@ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr, } static int cz_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, int level) + enum pp_clock_type type, uint32_t mask) { if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) return -EINVAL; @@ -1738,10 +1738,10 @@ static int cz_force_clock_level(struct pp_hwmgr *hwmgr, case PP_SCLK: smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetSclkSoftMin, - (1 << level)); + mask); smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetSclkSoftMax, - (1 << level)); + mask); break; default: break; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index dc836d3e92b5..f8d49f1b44f5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -5113,7 +5113,7 @@ static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t siz } static int fiji_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, int level) + enum pp_clock_type type, uint32_t mask) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -5125,20 +5125,30 @@ static int fiji_force_clock_level(struct pp_hwmgr *hwmgr, if (!data->sclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask); break; + case PP_MCLK: if (!data->mclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask); break; + case PP_PCIE: + { + uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; + uint32_t level = 0; + + while (tmp >>= 1) + level++; + if (!data->pcie_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_PCIeDPM_ForceLevel, - (1 << level)); + level); break; + } default: break; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 2ab3bb25d175..79192c301d78 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -4767,7 +4767,7 @@ static int polaris10_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_ } static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, int level) + enum pp_clock_type type, uint32_t mask) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -4779,20 +4779,28 @@ static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr, if (!data->sclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask); break; case PP_MCLK: if (!data->mclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask); break; case PP_PCIE: + { + uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; + uint32_t level = 0; + + while (tmp >>= 1) + level++; + if (!data->pcie_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_PCIeDPM_ForceLevel, - (1 << level)); + level); break; + } default: break; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 0242e348e755..9040225bec90 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -6075,7 +6075,7 @@ static int tonga_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t si } static int tonga_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, int level) + enum pp_clock_type type, uint32_t mask) { struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); @@ -6087,20 +6087,28 @@ static int tonga_force_clock_level(struct pp_hwmgr *hwmgr, if (!data->sclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask); break; case PP_MCLK: if (!data->mclk_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, - (1 << level)); + data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask); break; case PP_PCIE: + { + uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; + uint32_t level = 0; + + while (tmp >>= 1) + level++; + if (!data->pcie_dpm_key_disabled) smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_PCIeDPM_ForceLevel, - (1 << level)); + level); break; + } default: break; } diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index e5f2ee749fa6..50b367d44307 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -340,7 +340,7 @@ struct amd_powerplay_funcs { int (*get_pp_num_states)(void *handle, struct pp_states_info *data); int (*get_pp_table)(void *handle, char **table); int (*set_pp_table)(void *handle, const char *buf, size_t size); - int (*force_clock_level)(void *handle, enum pp_clock_type type, int level); + int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 12285a989eff..b1a9ae509ed8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -335,7 +335,7 @@ struct pp_hwmgr_func { int (*power_off_asic)(struct pp_hwmgr *hwmgr); int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table); int (*set_pp_table)(struct pp_hwmgr *hwmgr, const char *buf, size_t size); - int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, int level); + int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable); }; -- 2.30.2