[PATCH 08/10] drm/amd/pp: Implement AutoWattman feature on Vega10
Rex Zhu
Rex.Zhu at amd.com
Sat Feb 24 13:56:05 UTC 2018
based on the engine activity read from smu, driver will
notify smu to adjust the behaviour of natural DPM.
Change-Id: I951390cae82eeacfdaea3917eb570aa57216cbd7
Signed-off-by: Rex Zhu <Rex.Zhu at amd.com>
---
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 65 +++++++++++++++++++++-
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 11 +++-
2 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 22a42c9..2336f1f 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -766,7 +766,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
vega10_set_default_registry_data(hwmgr);
data->disable_dpm_mask = 0xff;
- data->workload_mask = 0xff;
+ data->workload_index = 0xff;
/* need to set voltage control types before EVV patching */
data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
@@ -4942,6 +4942,67 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
return 0;
}
+static void vega10_start_auto_wattman(struct pp_hwmgr *hwmgr, bool en)
+{
+ if (en)
+ schedule_delayed_work(&hwmgr->wattman_update_work, WATTMAM_SAMPLE_PERIOD);
+ else
+ cancel_delayed_work_sync(&hwmgr->wattman_update_work);
+}
+
+static void vega10_auto_wattman_get_data(struct pp_hwmgr *hwmgr)
+{
+ struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+ uint32_t activity_percent;
+
+ smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0);
+ vega10_read_arg_from_smc(hwmgr, &activity_percent);
+ data->wattman_data.average_sclk_busy = activity_percent > 100 ? 100 : activity_percent;
+
+ pr_debug("average sclk busy: %d\n", data->wattman_data.average_sclk_busy);
+
+ return;
+}
+
+#define Vega10_AutoWattMan_Setting_Max 5
+
+uint32_t Vega10_AutoWattMan_Setting[Vega10_AutoWattMan_Setting_Max] = {
+ PP_SMC_POWER_PROFILE_POWERSAVING,
+ PP_SMC_POWER_PROFILE_VIDEO,
+ PP_SMC_POWER_PROFILE_FULLSCREEN3D,
+ PP_SMC_POWER_PROFILE_VR,
+ PP_SMC_POWER_PROFILE_COMPUTE};
+
+static void vega10_auto_wattman_algorithm(struct pp_hwmgr *hwmgr)
+{
+ struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+ uint32_t threshold = AutoWattmanAlgorithmThreshold;
+
+ if (data->wattman_data.average_sclk_busy < threshold){
+ if (data->workload_index > 0)
+ data->workload_index -= 1;
+ } else {
+ if (data->workload_index < (Vega10_AutoWattMan_Setting_Max - 1))
+ data->workload_index += 1;
+ }
+}
+
+static int vega10_update_auto_wattman(struct pp_hwmgr *hwmgr)
+{
+ struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+
+ vega10_auto_wattman_get_data(hwmgr);
+ vega10_auto_wattman_algorithm(hwmgr);
+
+ if (hwmgr->power_profile_mode != Vega10_AutoWattMan_Setting[data->workload_index]) {
+ hwmgr->power_profile_mode = Vega10_AutoWattMan_Setting[data->workload_index];
+ smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+ 1<<hwmgr->power_profile_mode);
+ }
+
+ return 0;
+}
+
static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
.backend_init = vega10_hwmgr_backend_init,
.backend_fini = vega10_hwmgr_backend_fini,
@@ -5000,6 +5061,8 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
.get_power_profile_mode = vega10_get_power_profile_mode,
.set_power_profile_mode = vega10_set_power_profile_mode,
.set_power_limit = vega10_set_power_limit,
+ .update_auto_wattman = vega10_update_auto_wattman,
+ .start_auto_wattman = vega10_start_auto_wattman,
};
int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
index ab3e879..a12c170 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
@@ -36,6 +36,8 @@
#define WaterMarksExist 1
#define WaterMarksLoaded 2
+#define AutoWattmanAlgorithmThreshold 80
+
enum {
GNLD_DPM_PREFETCHER = 0,
GNLD_DPM_GFXCLK,
@@ -299,6 +301,11 @@ struct vega10_odn_fan_table {
uint32_t min_fan_limit;
};
+struct vega10_auto_wattman_data {
+ uint32_t average_sclk_busy;
+ uint32_t average_mclk_busy;
+};
+
struct vega10_hwmgr {
struct vega10_dpm_table dpm_table;
struct vega10_dpm_table golden_dpm_table;
@@ -374,8 +381,8 @@ struct vega10_hwmgr {
uint32_t apply_overdrive_next_settings_mask;
/* ---- Workload Mask ---- */
- uint32_t workload_mask;
-
+ uint32_t workload_index;
+ struct vega10_auto_wattman_data wattman_data;
/* ---- SMU9 ---- */
struct smu_features smu_features[GNLD_FEATURES_MAX];
struct vega10_smc_state_table smc_state_table;
--
1.9.1
More information about the amd-gfx
mailing list