Commit 5632708f authored by Eric Huang's avatar Eric Huang Committed by Alex Deucher

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: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarEric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 51224389
...@@ -362,16 +362,23 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, ...@@ -362,16 +362,23 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level; 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) { if (ret) {
count = -EINVAL; count = -EINVAL;
goto fail; goto fail;
}
mask |= 1 << level;
} }
if (adev->pp_enabled) if (adev->pp_enabled)
amdgpu_dpm_force_clock_level(adev, PP_SCLK, level); amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
fail: fail:
return count; return count;
} }
...@@ -399,16 +406,23 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, ...@@ -399,16 +406,23 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level; 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) { if (ret) {
count = -EINVAL; count = -EINVAL;
goto fail; goto fail;
}
mask |= 1 << level;
} }
if (adev->pp_enabled) if (adev->pp_enabled)
amdgpu_dpm_force_clock_level(adev, PP_MCLK, level); amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
fail: fail:
return count; return count;
} }
...@@ -436,16 +450,23 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, ...@@ -436,16 +450,23 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level; 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) { if (ret) {
count = -EINVAL; count = -EINVAL;
goto fail; goto fail;
}
mask |= 1 << level;
} }
if (adev->pp_enabled) if (adev->pp_enabled)
amdgpu_dpm_force_clock_level(adev, PP_PCIE, level); amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
fail: fail:
return count; return count;
} }
......
...@@ -763,7 +763,7 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) ...@@ -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, 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; struct pp_hwmgr *hwmgr;
...@@ -779,7 +779,7 @@ static int pp_dpm_force_clock_level(void *handle, ...@@ -779,7 +779,7 @@ static int pp_dpm_force_clock_level(void *handle,
return 0; 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, static int pp_dpm_print_clock_levels(void *handle,
......
...@@ -1729,7 +1729,7 @@ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr, ...@@ -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, 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) if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
return -EINVAL; return -EINVAL;
...@@ -1738,10 +1738,10 @@ static int cz_force_clock_level(struct pp_hwmgr *hwmgr, ...@@ -1738,10 +1738,10 @@ static int cz_force_clock_level(struct pp_hwmgr *hwmgr,
case PP_SCLK: case PP_SCLK:
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SetSclkSoftMin, PPSMC_MSG_SetSclkSoftMin,
(1 << level)); mask);
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SetSclkSoftMax, PPSMC_MSG_SetSclkSoftMax,
(1 << level)); mask);
break; break;
default: default:
break; break;
......
...@@ -5113,7 +5113,7 @@ static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t siz ...@@ -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, 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); struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
...@@ -5125,20 +5125,30 @@ static int fiji_force_clock_level(struct pp_hwmgr *hwmgr, ...@@ -5125,20 +5125,30 @@ static int fiji_force_clock_level(struct pp_hwmgr *hwmgr,
if (!data->sclk_dpm_key_disabled) if (!data->sclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SCLKDPM_SetEnabledMask, PPSMC_MSG_SCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
break; break;
case PP_MCLK: case PP_MCLK:
if (!data->mclk_dpm_key_disabled) if (!data->mclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_MCLKDPM_SetEnabledMask, PPSMC_MSG_MCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
break; break;
case PP_PCIE: 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) if (!data->pcie_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_PCIeDPM_ForceLevel, PPSMC_MSG_PCIeDPM_ForceLevel,
(1 << level)); level);
break; break;
}
default: default:
break; break;
} }
......
...@@ -4767,7 +4767,7 @@ static int polaris10_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_ ...@@ -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, 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); struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
...@@ -4779,20 +4779,28 @@ static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr, ...@@ -4779,20 +4779,28 @@ static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr,
if (!data->sclk_dpm_key_disabled) if (!data->sclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SCLKDPM_SetEnabledMask, PPSMC_MSG_SCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
break; break;
case PP_MCLK: case PP_MCLK:
if (!data->mclk_dpm_key_disabled) if (!data->mclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_MCLKDPM_SetEnabledMask, PPSMC_MSG_MCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
break; break;
case PP_PCIE: 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) if (!data->pcie_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_PCIeDPM_ForceLevel, PPSMC_MSG_PCIeDPM_ForceLevel,
(1 << level)); level);
break; break;
}
default: default:
break; break;
} }
......
...@@ -6075,7 +6075,7 @@ static int tonga_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t si ...@@ -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, 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); struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
...@@ -6087,20 +6087,28 @@ static int tonga_force_clock_level(struct pp_hwmgr *hwmgr, ...@@ -6087,20 +6087,28 @@ static int tonga_force_clock_level(struct pp_hwmgr *hwmgr,
if (!data->sclk_dpm_key_disabled) if (!data->sclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SCLKDPM_SetEnabledMask, PPSMC_MSG_SCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
break; break;
case PP_MCLK: case PP_MCLK:
if (!data->mclk_dpm_key_disabled) if (!data->mclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_MCLKDPM_SetEnabledMask, PPSMC_MSG_MCLKDPM_SetEnabledMask,
(1 << level)); data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
break; break;
case PP_PCIE: 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) if (!data->pcie_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_PCIeDPM_ForceLevel, PPSMC_MSG_PCIeDPM_ForceLevel,
(1 << level)); level);
break; break;
}
default: default:
break; break;
} }
......
...@@ -340,7 +340,7 @@ struct amd_powerplay_funcs { ...@@ -340,7 +340,7 @@ struct amd_powerplay_funcs {
int (*get_pp_num_states)(void *handle, struct pp_states_info *data); int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
int (*get_pp_table)(void *handle, char **table); int (*get_pp_table)(void *handle, char **table);
int (*set_pp_table)(void *handle, const char *buf, size_t size); 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); int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
}; };
......
...@@ -335,7 +335,7 @@ struct pp_hwmgr_func { ...@@ -335,7 +335,7 @@ struct pp_hwmgr_func {
int (*power_off_asic)(struct pp_hwmgr *hwmgr); int (*power_off_asic)(struct pp_hwmgr *hwmgr);
int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table); 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 (*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 (*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); int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable);
}; };
......
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