]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amdgpu/swsmu: use percent rather than rpm for manual fan control (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Thu, 28 Jan 2021 16:48:17 +0000 (11:48 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 1 Feb 2021 16:51:47 +0000 (11:51 -0500)
On some boards the rpm interface apparently does not work at all
leading to the fan not spinning or spinning at strange speeds.
Both interfaces work properly on the boards I have.
Let's try and use the percent interface instead.

v2: rebase on revert

Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1408
Reviewed-by: Evan Quan <evan.quan@amd.com> (v1)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c

index 7c5c7d605e652ff362c0a486c3c53a4759cec293..44279c2afccbad6910f08cb0daa5133b292efd8d 100644 (file)
@@ -173,7 +173,7 @@ enum smu_memory_pool_size
 struct smu_user_dpm_profile {
        uint32_t fan_mode;
        uint32_t power_limit;
-       uint32_t fan_speed_rpm;
+       uint32_t fan_speed_percent;
        uint32_t flags;
 
        /* user clock state information */
@@ -472,7 +472,7 @@ struct smu_context
        struct work_struct interrupt_work;
 
        unsigned fan_max_rpm;
-       unsigned manual_fan_speed_rpm;
+       unsigned manual_fan_speed_percent;
 
        uint32_t gfx_default_hard_min_freq;
        uint32_t gfx_default_soft_max_freq;
@@ -648,9 +648,9 @@ struct pptable_funcs {
        bool (*is_dpm_running)(struct smu_context *smu);
 
        /**
-        * @get_fan_speed_rpm: Get the current fan speed in RPM.
+        * @get_fan_speed_percent: Get the current fan speed in percent.
         */
-       int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
+       int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
 
        /**
         * @set_watermarks_table: Configure and upload the watermarks tables to
@@ -951,10 +951,10 @@ struct pptable_funcs {
        int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
 
        /**
-        * @set_fan_speed_rpm: Set a static fan speed in RPM.
+        * @set_fan_speed_percent: Set a static fan speed in percent.
         */
-       int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
        int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
+
        /**
         * @set_xgmi_pstate: Set inter-chip global memory interconnect pstate.
         * &pstate: Pstate to set. D0 if Nonzero, D3 otherwise.
index 1dfccdfc64916a73bf6626f60e0d75775f748400..c7d57e9555cc0197e0e28db133ce8eae0e34c704 100644 (file)
@@ -203,14 +203,8 @@ int
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode);
 
-int
-smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed);
-
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed);
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed);
+int smu_v11_0_set_fan_speed_percent(struct smu_context *smu,
+                                   uint32_t speed);
 
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate);
index dffa6ff7ba1f8fdb6cc55cf602b3bc6b5600987b..1c7ac81fe417af24db940113f44e13c3340c4c33 100644 (file)
@@ -368,8 +368,8 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
                        return;
                }
 
-               if (!ret && smu->user_dpm_profile.fan_speed_rpm) {
-                       ret = smu_set_fan_speed_rpm(smu, smu->user_dpm_profile.fan_speed_rpm);
+               if (!ret && smu->user_dpm_profile.fan_speed_percent) {
+                       ret = smu_set_fan_speed_percent(smu, smu->user_dpm_profile.fan_speed_percent);
                        if (ret)
                                dev_err(smu->adev->dev, "Failed to set manual fan speed\n");
                }
@@ -2025,6 +2025,7 @@ int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled)
 
 int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
 {
+       u32 percent;
        int ret = 0;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
@@ -2032,10 +2033,11 @@ int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->set_fan_speed_rpm) {
-               ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
+       if (smu->ppt_funcs->set_fan_speed_percent) {
+               percent = speed * 100 / smu->fan_max_rpm;
+               ret = smu->ppt_funcs->set_fan_speed_percent(smu, percent);
                if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
-                       smu->user_dpm_profile.fan_speed_rpm = speed;
+                       smu->user_dpm_profile.fan_speed_percent = percent;
        }
 
        mutex_unlock(&smu->mutex);
@@ -2270,7 +2272,7 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value)
        /* reset user dpm fan speed */
        if (!ret && value != AMD_FAN_CTRL_MANUAL &&
                        smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
-               smu->user_dpm_profile.fan_speed_rpm = 0;
+               smu->user_dpm_profile.fan_speed_percent = 0;
 
        return ret;
 }
@@ -2279,17 +2281,15 @@ int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed)
 {
        int ret = 0;
        uint32_t percent;
-       uint32_t current_rpm;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
                return -EOPNOTSUPP;
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->get_fan_speed_rpm) {
-               ret = smu->ppt_funcs->get_fan_speed_rpm(smu, &current_rpm);
+       if (smu->ppt_funcs->get_fan_speed_percent) {
+               ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
                if (!ret) {
-                       percent = current_rpm * 100 / smu->fan_max_rpm;
                        *speed = percent > 100 ? 100 : percent;
                }
        }
@@ -2309,8 +2309,13 @@ int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->set_fan_speed_percent)
+       if (smu->ppt_funcs->set_fan_speed_percent) {
+               if (speed > 100)
+                       speed = 100;
                ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed);
+               if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
+                       smu->user_dpm_profile.fan_speed_percent = speed;
+       }
 
        mutex_unlock(&smu->mutex);
 
@@ -2320,14 +2325,17 @@ int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
 int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed)
 {
        int ret = 0;
+       u32 percent;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
                return -EOPNOTSUPP;
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->get_fan_speed_rpm)
-               ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed);
+       if (smu->ppt_funcs->get_fan_speed_percent) {
+               ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
+               *speed = percent * smu->fan_max_rpm / 100;
+       }
 
        mutex_unlock(&smu->mutex);
 
index 16db0b506b0de0a6ee3be4a80f385e861169e8c5..f0cc4de9ced5008b1141a9b4fe75c04d15c58e81 100644 (file)
@@ -1080,15 +1080,27 @@ static int arcturus_read_sensor(struct smu_context *smu,
        return ret;
 }
 
-static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
-                                     uint32_t *speed)
+static int arcturus_get_fan_speed_percent(struct smu_context *smu,
+                                         uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return arcturus_get_smu_metrics_data(smu,
-                                            METRICS_CURR_FANSPEED,
-                                            speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = arcturus_get_smu_metrics_data(smu,
+                                                   METRICS_CURR_FANSPEED,
+                                                   &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int arcturus_get_fan_parameters(struct smu_context *smu)
@@ -2281,7 +2293,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .print_clk_levels = arcturus_print_clk_levels,
        .force_clk_levels = arcturus_force_clk_levels,
        .read_sensor = arcturus_read_sensor,
-       .get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
+       .get_fan_speed_percent = arcturus_get_fan_speed_percent,
        .get_power_profile_mode = arcturus_get_power_profile_mode,
        .set_power_profile_mode = arcturus_set_power_profile_mode,
        .set_performance_level = arcturus_set_performance_level,
@@ -2327,7 +2339,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
        .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
index 43869149dcf3bf4ffc4fcfe5de43ad76f15f848a..f7f78daffd2759fb8c07db9a7bb10cf6dd20eb1d 100644 (file)
@@ -1317,15 +1317,27 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static int navi10_get_fan_speed_rpm(struct smu_context *smu,
-                                   uint32_t *speed)
+static int navi10_get_fan_speed_percent(struct smu_context *smu,
+                                       uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return navi10_get_smu_metrics_data(smu,
-                                          METRICS_CURR_FANSPEED,
-                                          speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = navi10_get_smu_metrics_data(smu,
+                                                 METRICS_CURR_FANSPEED,
+                                                 &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int navi10_get_fan_parameters(struct smu_context *smu)
@@ -2413,7 +2425,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .display_config_changed = navi10_display_config_changed,
        .notify_smc_display_config = navi10_notify_smc_display_config,
        .is_dpm_running = navi10_is_dpm_running,
-       .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
+       .get_fan_speed_percent = navi10_get_fan_speed_percent,
        .get_power_profile_mode = navi10_get_power_profile_mode,
        .set_power_profile_mode = navi10_set_power_profile_mode,
        .set_watermarks_table = navi10_set_watermarks_table,
@@ -2457,7 +2469,6 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
        .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
index 52ace804f5b31b6ddaddf37c8e7aa44c7e0391ab..e3ba40d9f83f9900768de9c27952720391ac14f7 100644 (file)
@@ -1237,15 +1237,27 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
-                                   uint32_t *speed)
+static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu,
+                                               uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return sienna_cichlid_get_smu_metrics_data(smu,
-                                               METRICS_CURR_FANSPEED,
-                                               speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_CURR_FANSPEED,
+                                                         &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
@@ -3087,7 +3099,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
        .display_config_changed = sienna_cichlid_display_config_changed,
        .notify_smc_display_config = sienna_cichlid_notify_smc_display_config,
        .is_dpm_running = sienna_cichlid_is_dpm_running,
-       .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm,
+       .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent,
        .get_power_profile_mode = sienna_cichlid_get_power_profile_mode,
        .set_power_profile_mode = sienna_cichlid_set_power_profile_mode,
        .set_watermarks_table = sienna_cichlid_set_watermarks_table,
@@ -3131,7 +3143,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
        .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
index 6d84aea0cc38be83ad0a07817676823ab290574b..cf6176afd4d539b5d85bec22e89ab04c7318e878 100644 (file)
@@ -1137,10 +1137,10 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
 uint32_t
 smu_v11_0_get_fan_control_mode(struct smu_context *smu)
 {
-       if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
-               return AMD_FAN_CTRL_MANUAL;
-       else
+       if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return AMD_FAN_CTRL_AUTO;
+       else
+               return smu->user_dpm_profile.fan_mode;
 }
 
 static int
@@ -1231,58 +1231,6 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
        return ret;
 }
 
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       int ret;
-       uint32_t tach_period, crystal_clock_freq;
-
-       if (!speed)
-               return -EINVAL;
-
-       ret = smu_v11_0_auto_fan_control(smu, 0);
-       if (ret)
-               return ret;
-
-       /*
-        * crystal_clock_freq div by 4 is required since the fan control
-        * module refers to 25MHz
-        */
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
-       tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
-       WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
-                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                  CG_TACH_CTRL, TARGET_PERIOD,
-                                  tach_period));
-
-       ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
-
-       return ret;
-}
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       uint32_t tach_period, crystal_clock_freq;
-       uint64_t tmp64;
-
-       tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                   CG_TACH_CTRL, TARGET_PERIOD);
-       if (!tach_period)
-               return -EINVAL;
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev);
-
-       tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
-       do_div(tmp64, (tach_period * 8));
-       *speed = (uint32_t)tmp64;
-
-       return 0;
-}
-
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate)
 {