[PATCH 2/2] drm/amd/pm: handle custom workload profiles across suspend
Alex Deucher
alexander.deucher at amd.com
Tue Nov 12 20:28:47 UTC 2024
If a custom workload profile was provided, save the custom state
and reapply if the custom profile is enabled when applying the
workload profile.
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
Cc: Kenneth Feng <kenneth.feng at amd.com>
Cc: Lijo Lazar <lijo.lazar at amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 3 +
.../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 128 +++++++++-------
.../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 141 ++++++++++-------
.../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 144 ++++++++++--------
.../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 126 ++++++++-------
.../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 114 ++++++++------
.../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 132 +++++++++-------
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 12 ++
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 3 +
9 files changed, 484 insertions(+), 319 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index da7558a65c09..ae57394beb84 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -562,6 +562,9 @@ struct smu_context {
uint32_t power_profile_mode;
uint32_t workload_refcount[PP_SMC_POWER_PROFILE_COUNT];
struct mutex workload_lock;
+ /* backend specific custom workload settings */
+ long custom_profile_input[10];
+ bool custom_profile_size;
bool pm_enabled;
bool is_apu;
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 1e44cf6fec4b..72dca191263f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1441,72 +1441,87 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static int arcturus_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input,
+ uint32_t size)
+{
+ DpmActivityMonitorCoeffInt_t activity_monitor;
+ int ret;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor.Gfx_FPS = input[1];
+ activity_monitor.Gfx_UseRlcBusy = input[2];
+ activity_monitor.Gfx_MinActiveFreqType = input[3];
+ activity_monitor.Gfx_MinActiveFreq = input[4];
+ activity_monitor.Gfx_BoosterFreqType = input[5];
+ activity_monitor.Gfx_BoosterFreq = input[6];
+ activity_monitor.Gfx_PD_Data_limit_c = input[7];
+ activity_monitor.Gfx_PD_Data_error_coeff = input[8];
+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 1: /* Uclk */
+ activity_monitor.Mem_FPS = input[1];
+ activity_monitor.Mem_UseRlcBusy = input[2];
+ activity_monitor.Mem_MinActiveFreqType = input[3];
+ activity_monitor.Mem_MinActiveFreq = input[4];
+ activity_monitor.Mem_BoosterFreqType = input[5];
+ activity_monitor.Mem_BoosterFreq = input[6];
+ activity_monitor.Mem_PD_Data_limit_c = input[7];
+ activity_monitor.Mem_PD_Data_error_coeff = input[8];
+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
static int arcturus_set_power_profile_mode(struct smu_context *smu,
long *input,
uint32_t size,
bool enable)
{
- DpmActivityMonitorCoeffInt_t activity_monitor;
int workload_type = 0;
uint32_t profile_mode = input[size];
- int ret = 0;
+ int i, ret;
if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
return -EINVAL;
}
- if (enable &&
- (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
+ if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
(smu->smc_fw_version >= 0x360d00)) {
- if (size != 10)
- return -EINVAL;
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
-
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor.Gfx_FPS = input[1];
- activity_monitor.Gfx_UseRlcBusy = input[2];
- activity_monitor.Gfx_MinActiveFreqType = input[3];
- activity_monitor.Gfx_MinActiveFreq = input[4];
- activity_monitor.Gfx_BoosterFreqType = input[5];
- activity_monitor.Gfx_BoosterFreq = input[6];
- activity_monitor.Gfx_PD_Data_limit_c = input[7];
- activity_monitor.Gfx_PD_Data_error_coeff = input[8];
- activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Uclk */
- activity_monitor.Mem_FPS = input[1];
- activity_monitor.Mem_UseRlcBusy = input[2];
- activity_monitor.Mem_MinActiveFreqType = input[3];
- activity_monitor.Mem_MinActiveFreq = input[4];
- activity_monitor.Mem_BoosterFreqType = input[5];
- activity_monitor.Mem_BoosterFreq = input[6];
- activity_monitor.Mem_PD_Data_limit_c = input[7];
- activity_monitor.Mem_PD_Data_error_coeff = input[8];
- activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
- return -EINVAL;
- }
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor),
- true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (enable) {
+ if (size != 10)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -1526,6 +1541,15 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
smu->workload_mask |= (1 << workload_type);
else
smu->workload_mask &= ~(1 << workload_type);
+
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = arcturus_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
+
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetWorkloadMask,
smu->workload_mask,
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 d944a9f954d0..339e64b1e95b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2006,74 +2006,90 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
return size;
}
+static int navi10_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input,
+ uint32_t size)
+{
+ DpmActivityMonitorCoeffInt_t activity_monitor;
+ int ret;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor.Gfx_FPS = input[1];
+ activity_monitor.Gfx_MinFreqStep = input[2];
+ activity_monitor.Gfx_MinActiveFreqType = input[3];
+ activity_monitor.Gfx_MinActiveFreq = input[4];
+ activity_monitor.Gfx_BoosterFreqType = input[5];
+ activity_monitor.Gfx_BoosterFreq = input[6];
+ activity_monitor.Gfx_PD_Data_limit_c = input[7];
+ activity_monitor.Gfx_PD_Data_error_coeff = input[8];
+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 1: /* Socclk */
+ activity_monitor.Soc_FPS = input[1];
+ activity_monitor.Soc_MinFreqStep = input[2];
+ activity_monitor.Soc_MinActiveFreqType = input[3];
+ activity_monitor.Soc_MinActiveFreq = input[4];
+ activity_monitor.Soc_BoosterFreqType = input[5];
+ activity_monitor.Soc_BoosterFreq = input[6];
+ activity_monitor.Soc_PD_Data_limit_c = input[7];
+ activity_monitor.Soc_PD_Data_error_coeff = input[8];
+ activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 2: /* Memclk */
+ activity_monitor.Mem_FPS = input[1];
+ activity_monitor.Mem_MinFreqStep = input[2];
+ activity_monitor.Mem_MinActiveFreqType = input[3];
+ activity_monitor.Mem_MinActiveFreq = input[4];
+ activity_monitor.Mem_BoosterFreqType = input[5];
+ activity_monitor.Mem_BoosterFreq = input[6];
+ activity_monitor.Mem_PD_Data_limit_c = input[7];
+ activity_monitor.Mem_PD_Data_error_coeff = input[8];
+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
static int navi10_set_power_profile_mode(struct smu_context *smu, long *input,
uint32_t size, bool enable)
{
- DpmActivityMonitorCoeffInt_t activity_monitor;
- int workload_type, ret = 0;
uint32_t profile_mode = input[size];
+ int workload_type, i, ret = 0;
if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
return -EINVAL;
}
- if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 10)
- return -EINVAL;
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
-
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor.Gfx_FPS = input[1];
- activity_monitor.Gfx_MinFreqStep = input[2];
- activity_monitor.Gfx_MinActiveFreqType = input[3];
- activity_monitor.Gfx_MinActiveFreq = input[4];
- activity_monitor.Gfx_BoosterFreqType = input[5];
- activity_monitor.Gfx_BoosterFreq = input[6];
- activity_monitor.Gfx_PD_Data_limit_c = input[7];
- activity_monitor.Gfx_PD_Data_error_coeff = input[8];
- activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Socclk */
- activity_monitor.Soc_FPS = input[1];
- activity_monitor.Soc_MinFreqStep = input[2];
- activity_monitor.Soc_MinActiveFreqType = input[3];
- activity_monitor.Soc_MinActiveFreq = input[4];
- activity_monitor.Soc_BoosterFreqType = input[5];
- activity_monitor.Soc_BoosterFreq = input[6];
- activity_monitor.Soc_PD_Data_limit_c = input[7];
- activity_monitor.Soc_PD_Data_error_coeff = input[8];
- activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
- break;
- case 2: /* Memclk */
- activity_monitor.Mem_FPS = input[1];
- activity_monitor.Mem_MinFreqStep = input[2];
- activity_monitor.Mem_MinActiveFreqType = input[3];
- activity_monitor.Mem_MinActiveFreq = input[4];
- activity_monitor.Mem_BoosterFreqType = input[5];
- activity_monitor.Mem_BoosterFreq = input[6];
- activity_monitor.Mem_PD_Data_limit_c = input[7];
- activity_monitor.Mem_PD_Data_error_coeff = input[8];
- activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
- return -EINVAL;
- }
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ if (enable) {
+ if (size != 10)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -2088,6 +2104,15 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input,
smu->workload_mask |= (1 << workload_type);
else
smu->workload_mask &= ~(1 << workload_type);
+
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = navi10_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
smu->workload_mask, NULL);
if (ret)
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 4967e087088b..8580fef73222 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
@@ -1704,78 +1704,93 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
return size;
}
-static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,
- long *input, uint32_t size,
- bool enable)
+static int sienna_cichlid_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input, uint32_t size)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- uint32_t profile_mode = input[size];
- int workload_type, ret = 0;
+ int ret;
- if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[1];
+ activity_monitor->Gfx_MinFreqStep = input[2];
+ activity_monitor->Gfx_MinActiveFreqType = input[3];
+ activity_monitor->Gfx_MinActiveFreq = input[4];
+ activity_monitor->Gfx_BoosterFreqType = input[5];
+ activity_monitor->Gfx_BoosterFreq = input[6];
+ activity_monitor->Gfx_PD_Data_limit_c = input[7];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[8];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 1: /* Socclk */
+ activity_monitor->Fclk_FPS = input[1];
+ activity_monitor->Fclk_MinFreqStep = input[2];
+ activity_monitor->Fclk_MinActiveFreqType = input[3];
+ activity_monitor->Fclk_MinActiveFreq = input[4];
+ activity_monitor->Fclk_BoosterFreqType = input[5];
+ activity_monitor->Fclk_BoosterFreq = input[6];
+ activity_monitor->Fclk_PD_Data_limit_c = input[7];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[8];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 2: /* Memclk */
+ activity_monitor->Mem_FPS = input[1];
+ activity_monitor->Mem_MinFreqStep = input[2];
+ activity_monitor->Mem_MinActiveFreqType = input[3];
+ activity_monitor->Mem_MinActiveFreq = input[4];
+ activity_monitor->Mem_BoosterFreqType = input[5];
+ activity_monitor->Mem_BoosterFreq = input[6];
+ activity_monitor->Mem_PD_Data_limit_c = input[7];
+ activity_monitor->Mem_PD_Data_error_coeff = input[8];
+ activity_monitor->Mem_PD_Data_error_rate_coeff = input[9];
+ break;
+ default:
return -EINVAL;
}
- if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 10)
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ return ret;
+}
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinFreqStep = input[2];
- activity_monitor->Gfx_MinActiveFreqType = input[3];
- activity_monitor->Gfx_MinActiveFreq = input[4];
- activity_monitor->Gfx_BoosterFreqType = input[5];
- activity_monitor->Gfx_BoosterFreq = input[6];
- activity_monitor->Gfx_PD_Data_limit_c = input[7];
- activity_monitor->Gfx_PD_Data_error_coeff = input[8];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Socclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinFreqStep = input[2];
- activity_monitor->Fclk_MinActiveFreqType = input[3];
- activity_monitor->Fclk_MinActiveFreq = input[4];
- activity_monitor->Fclk_BoosterFreqType = input[5];
- activity_monitor->Fclk_BoosterFreq = input[6];
- activity_monitor->Fclk_PD_Data_limit_c = input[7];
- activity_monitor->Fclk_PD_Data_error_coeff = input[8];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[9];
- break;
- case 2: /* Memclk */
- activity_monitor->Mem_FPS = input[1];
- activity_monitor->Mem_MinFreqStep = input[2];
- activity_monitor->Mem_MinActiveFreqType = input[3];
- activity_monitor->Mem_MinActiveFreq = input[4];
- activity_monitor->Mem_BoosterFreqType = input[5];
- activity_monitor->Mem_BoosterFreq = input[6];
- activity_monitor->Mem_PD_Data_limit_c = input[7];
- activity_monitor->Mem_PD_Data_error_coeff = input[8];
- activity_monitor->Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
- return -EINVAL;
- }
+static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,
+ long *input, uint32_t size,
+ bool enable)
+{
+ uint32_t profile_mode = input[size];
+ int workload_type, i, ret = 0;
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
+ dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
+ return -EINVAL;
+ }
+
+ if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ if (enable) {
+ if (size != 10)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -1790,6 +1805,15 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,
smu->workload_mask |= (1 << workload_type);
else
smu->workload_mask &= ~(1 << workload_type);
+
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = sienna_cichlid_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
smu->workload_mask, NULL);
if (ret)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 3cc734331891..e928719bf6b7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2571,16 +2571,70 @@ static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static int smu_v13_0_0_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input,
+ uint32_t size)
+{
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+ int ret;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[1];
+ activity_monitor->Gfx_MinActiveFreqType = input[2];
+ activity_monitor->Gfx_MinActiveFreq = input[3];
+ activity_monitor->Gfx_BoosterFreqType = input[4];
+ activity_monitor->Gfx_BoosterFreq = input[5];
+ activity_monitor->Gfx_PD_Data_limit_c = input[6];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[7];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
+ break;
+ case 1: /* Fclk */
+ activity_monitor->Fclk_FPS = input[1];
+ activity_monitor->Fclk_MinActiveFreqType = input[2];
+ activity_monitor->Fclk_MinActiveFreq = input[3];
+ activity_monitor->Fclk_BoosterFreqType = input[4];
+ activity_monitor->Fclk_BoosterFreq = input[5];
+ activity_monitor->Fclk_PD_Data_limit_c = input[6];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[7];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
long *input,
uint32_t size,
bool enable)
{
- DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
- DpmActivityMonitorCoeffInt_t *activity_monitor =
- &(activity_monitor_external.DpmActivityMonitorCoeffInt);
uint32_t profile_mode = input[size];
- int workload_type, ret = 0;
+ int workload_type, i, ret = 0;
u32 workload_mask;
if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
@@ -2588,53 +2642,15 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
return -EINVAL;
}
- if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 9)
- return -EINVAL;
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
-
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinActiveFreqType = input[2];
- activity_monitor->Gfx_MinActiveFreq = input[3];
- activity_monitor->Gfx_BoosterFreqType = input[4];
- activity_monitor->Gfx_BoosterFreq = input[5];
- activity_monitor->Gfx_PD_Data_limit_c = input[6];
- activity_monitor->Gfx_PD_Data_error_coeff = input[7];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinActiveFreqType = input[2];
- activity_monitor->Fclk_MinActiveFreq = input[3];
- activity_monitor->Fclk_BoosterFreqType = input[4];
- activity_monitor->Fclk_BoosterFreq = input[5];
- activity_monitor->Fclk_PD_Data_limit_c = input[6];
- activity_monitor->Fclk_PD_Data_error_coeff = input[7];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
- break;
- default:
- return -EINVAL;
- }
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ if (enable) {
+ if (size != 9)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -2666,6 +2682,14 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
smu->workload_mask |= 1 << workload_type;
}
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = smu_v13_0_0_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
+
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetWorkloadMask,
smu->workload_mask,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index 1aafd23857f0..e14d8d46ca2a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2528,63 +2528,78 @@ do { \
return result;
}
-static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
- long *input, uint32_t size,
- bool enable)
+static int smu_v13_0_7_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input, uint32_t size)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- uint32_t profile_mode = input[size];
- int workload_type, ret = 0;
+ int ret;
- if (profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_ActiveHystLimit = input[1];
+ activity_monitor->Gfx_IdleHystLimit = input[2];
+ activity_monitor->Gfx_FPS = input[3];
+ activity_monitor->Gfx_MinActiveFreqType = input[4];
+ activity_monitor->Gfx_BoosterFreqType = input[5];
+ activity_monitor->Gfx_MinActiveFreq = input[6];
+ activity_monitor->Gfx_BoosterFreq = input[7];
+ break;
+ case 1: /* Fclk */
+ activity_monitor->Fclk_ActiveHystLimit = input[1];
+ activity_monitor->Fclk_IdleHystLimit = input[2];
+ activity_monitor->Fclk_FPS = input[3];
+ activity_monitor->Fclk_MinActiveFreqType = input[4];
+ activity_monitor->Fclk_BoosterFreqType = input[5];
+ activity_monitor->Fclk_MinActiveFreq = input[6];
+ activity_monitor->Fclk_BoosterFreq = input[7];
+ break;
+ default:
return -EINVAL;
}
- if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 8)
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ return ret;
+}
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_ActiveHystLimit = input[1];
- activity_monitor->Gfx_IdleHystLimit = input[2];
- activity_monitor->Gfx_FPS = input[3];
- activity_monitor->Gfx_MinActiveFreqType = input[4];
- activity_monitor->Gfx_BoosterFreqType = input[5];
- activity_monitor->Gfx_MinActiveFreq = input[6];
- activity_monitor->Gfx_BoosterFreq = input[7];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_ActiveHystLimit = input[1];
- activity_monitor->Fclk_IdleHystLimit = input[2];
- activity_monitor->Fclk_FPS = input[3];
- activity_monitor->Fclk_MinActiveFreqType = input[4];
- activity_monitor->Fclk_BoosterFreqType = input[5];
- activity_monitor->Fclk_MinActiveFreq = input[6];
- activity_monitor->Fclk_BoosterFreq = input[7];
- break;
- default:
- return -EINVAL;
- }
+static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
+ long *input, uint32_t size,
+ bool enable)
+{
+ uint32_t profile_mode = input[size];
+ int workload_type, i, ret = 0;
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
+ dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
+ return -EINVAL;
+ }
+
+ if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ if (enable) {
+ if (size != 8)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -2599,6 +2614,15 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
smu->workload_mask |= (1 << workload_type);
else
smu->workload_mask &= ~(1 << workload_type);
+
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = smu_v13_0_7_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
smu->workload_mask, NULL);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index b64490bcfd62..ba586bbaade9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1717,69 +1717,85 @@ static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static int smu_v14_0_2_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input,
+ uint32_t size)
+{
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+ int ret;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[1];
+ activity_monitor->Gfx_MinActiveFreqType = input[2];
+ activity_monitor->Gfx_MinActiveFreq = input[3];
+ activity_monitor->Gfx_BoosterFreqType = input[4];
+ activity_monitor->Gfx_BoosterFreq = input[5];
+ activity_monitor->Gfx_PD_Data_limit_c = input[6];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[7];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
+ break;
+ case 1: /* Fclk */
+ activity_monitor->Fclk_FPS = input[1];
+ activity_monitor->Fclk_MinActiveFreqType = input[2];
+ activity_monitor->Fclk_MinActiveFreq = input[3];
+ activity_monitor->Fclk_BoosterFreqType = input[4];
+ activity_monitor->Fclk_BoosterFreq = input[5];
+ activity_monitor->Fclk_PD_Data_limit_c = input[6];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[7];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
long *input,
uint32_t size,
bool enable)
{
- DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
- DpmActivityMonitorCoeffInt_t *activity_monitor =
- &(activity_monitor_external.DpmActivityMonitorCoeffInt);
uint32_t profile_mode = input[size];
- int workload_type, ret = 0;
+ int workload_type, i, ret = 0;
if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
return -EINVAL;
}
- if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 9)
- return -EINVAL;
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
-
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinActiveFreqType = input[2];
- activity_monitor->Gfx_MinActiveFreq = input[3];
- activity_monitor->Gfx_BoosterFreqType = input[4];
- activity_monitor->Gfx_BoosterFreq = input[5];
- activity_monitor->Gfx_PD_Data_limit_c = input[6];
- activity_monitor->Gfx_PD_Data_error_coeff = input[7];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinActiveFreqType = input[2];
- activity_monitor->Fclk_MinActiveFreq = input[3];
- activity_monitor->Fclk_BoosterFreqType = input[4];
- activity_monitor->Fclk_BoosterFreq = input[5];
- activity_monitor->Fclk_PD_Data_limit_c = input[6];
- activity_monitor->Fclk_PD_Data_error_coeff = input[7];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
- break;
- default:
- return -EINVAL;
- }
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
+ if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ if (enable) {
+ if (size != 9)
+ return -EINVAL;
+ for (i = 0; i < size; i++)
+ smu->custom_profile_input[i] = input[i];
+ smu->custom_profile_size = size;
+ } else {
+ smu->custom_profile_size = 0;
}
}
@@ -1796,8 +1812,18 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
smu->workload_mask &= ~(1 << workload_type);
/* disable deep sleep if compute is enabled */
- if (profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)
- smu_v14_0_deep_sleep_control(smu, !enable);
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_COMPUTE))
+ smu_v14_0_deep_sleep_control(smu, false);
+ else
+ smu_v14_0_deep_sleep_control(smu, true);
+
+ if (smu_cmn_is_workload_profile_enabled(smu, PP_SMC_POWER_PROFILE_CUSTOM)) {
+ ret = smu_v14_0_2_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_input,
+ smu->custom_profile_size);
+ if (ret)
+ return ret;
+ }
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
smu->workload_mask, NULL);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 63c4f75fa118..5d70cebdc48a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1218,3 +1218,15 @@ void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy)
{
policy->desc = &xgmi_plpd_policy_desc;
}
+
+bool smu_cmn_is_workload_profile_enabled(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode)
+{
+ bool enabled;
+
+ mutex_lock(&smu->workload_lock);
+ enabled = smu->workload_refcount[profile_mode];
+ mutex_unlock(&smu->workload_lock);
+
+ return enabled;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 1de685defe85..11ad33a0b5a3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -147,5 +147,8 @@ 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);
+bool smu_cmn_is_workload_profile_enabled(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode);
+
#endif
#endif
--
2.47.0
More information about the amd-gfx
mailing list