]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/pm: add zero RPM OD setting support for SMU13
authorWolfgang Müller <wolf@oriole.systems>
Tue, 29 Oct 2024 11:17:52 +0000 (12:17 +0100)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 5 Nov 2024 15:33:30 +0000 (10:33 -0500)
Whilst we have support for setting fan curves there is no support for
disabling the zero RPM feature. Since the relevant bits are already
present in the OverDriveTable, hook them up to a sysctl setting so users
can influence this behaviour.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3489
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Wolfgang Müller <wolf@oriole.systems>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Documentation/gpu/amdgpu/thermal.rst
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c

index 6d942b5c58f0547bf1aa7abb0db0e9d522eb09b7..ec6c1f1d5a4a62b8dfbb94b470688c5928a7de5a 100644 (file)
@@ -100,6 +100,12 @@ fan_minimum_pwm
 .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
    :doc: fan_minimum_pwm
 
+fan_zero_rpm_enable
+----------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+   :doc: fan_zero_rpm_enable
+
 GFXOFF
 ======
 
index 2fa71f68205ebb62289815f429c9e6df4257d00f..80e4b5a7df234414508334a91adc916313bc1388 100644 (file)
@@ -119,6 +119,7 @@ enum pp_clock_type {
        OD_ACOUSTIC_TARGET,
        OD_FAN_TARGET_TEMPERATURE,
        OD_FAN_MINIMUM_PWM,
+       OD_FAN_ZERO_RPM_ENABLE,
 };
 
 enum amd_pp_sensors {
@@ -199,6 +200,7 @@ enum PP_OD_DPM_TABLE_COMMAND {
        PP_OD_EDIT_ACOUSTIC_TARGET,
        PP_OD_EDIT_FAN_TARGET_TEMPERATURE,
        PP_OD_EDIT_FAN_MINIMUM_PWM,
+       PP_OD_EDIT_FAN_ZERO_RPM_ENABLE,
 };
 
 struct pp_states_info {
index ea940773353cdfdf399b996c5a28ae49ba5039a2..cb96f1f8ca8d9a8c5ef87ef9563650502dde398e 100644 (file)
@@ -4109,6 +4109,60 @@ static umode_t fan_minimum_pwm_visible(struct amdgpu_device *adev)
        return umode;
 }
 
+/**
+ * DOC: fan_zero_rpm_enable
+ *
+ * The amdgpu driver provides a sysfs API for checking and adjusting the
+ * zero RPM feature.
+ *
+ * Reading back the file shows you the current setting and the permitted
+ * ranges if changable.
+ *
+ * Writing an integer to the file, change the setting accordingly.
+ *
+ * When you have finished the editing, write "c" (commit) to the file to commit
+ * your changes.
+ *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them.
+ */
+static ssize_t fan_zero_rpm_enable_show(struct kobject *kobj,
+                                          struct kobj_attribute *attr,
+                                          char *buf)
+{
+       struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+       struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+       return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_ZERO_RPM_ENABLE, buf);
+}
+
+static ssize_t fan_zero_rpm_enable_store(struct kobject *kobj,
+                                           struct kobj_attribute *attr,
+                                           const char *buf,
+                                           size_t count)
+{
+       struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+       struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+       return (ssize_t)amdgpu_distribute_custom_od_settings(adev,
+                                                            PP_OD_EDIT_FAN_ZERO_RPM_ENABLE,
+                                                            buf,
+                                                            count);
+}
+
+static umode_t fan_zero_rpm_enable_visible(struct amdgpu_device *adev)
+{
+       umode_t umode = 0000;
+
+       if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE)
+               umode |= S_IRUSR | S_IRGRP | S_IROTH;
+
+       if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET)
+               umode |= S_IWUSR;
+
+       return umode;
+}
+
 static struct od_feature_set amdgpu_od_set = {
        .containers = {
                [0] = {
@@ -4154,6 +4208,14 @@ static struct od_feature_set amdgpu_od_set = {
                                                .store = fan_minimum_pwm_store,
                                        },
                                },
+                               [5] = {
+                                       .name = "fan_zero_rpm_enable",
+                                       .ops = {
+                                               .is_visible = fan_zero_rpm_enable_visible,
+                                               .show = fan_zero_rpm_enable_show,
+                                               .store = fan_zero_rpm_enable_store,
+                                       },
+                               },
                        },
                },
        },
index f5bf41f21c4123930120e2b05b141a4329e9815d..b5daa12c0864a64af771ec3bf51432481db02f41 100644 (file)
@@ -328,6 +328,8 @@ struct config_table_setting
 #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET              BIT(7)
 #define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE                BIT(8)
 #define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET             BIT(9)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE    BIT(10)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET         BIT(11)
 
 struct amdgpu_pm {
        struct mutex            mutex;
index aa7c57b587650eb8e1bc698d21fcbd6fb7c4ac1f..3458674fe864e9addd9c5d25cb31c71d4f8ab631 100644 (file)
@@ -2895,6 +2895,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
                clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break;
        case OD_FAN_MINIMUM_PWM:
                clk_type = SMU_OD_FAN_MINIMUM_PWM; break;
+       case OD_FAN_ZERO_RPM_ENABLE:
+               clk_type = SMU_OD_FAN_ZERO_RPM_ENABLE; break;
        default:
                clk_type = SMU_CLK_COUNT; break;
        }
index e71a721c12b9851e2f7c88cddb99ad1defe097ab..e0abb449a3a1e91fb25205228e351da3d73349af 100644 (file)
@@ -313,6 +313,7 @@ enum smu_clk_type {
        SMU_OD_ACOUSTIC_TARGET,
        SMU_OD_FAN_TARGET_TEMPERATURE,
        SMU_OD_FAN_MINIMUM_PWM,
+       SMU_OD_FAN_ZERO_RPM_ENABLE,
        SMU_CLK_COUNT,
 };
 
index 1d29e99d7955779c64790bb7a0c13a6c6921ad2c..a7c62bb09aa0d79670f275ea35b29c5ed69874c6 100644 (file)
 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET              8
 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE           9
 #define PP_OD_FEATURE_FAN_MINIMUM_PWM                  10
+#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE              11
 
 #define LINK_SPEED_MAX                                 3
 
@@ -1130,6 +1131,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
                od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
                od_max_setting = overdrive_upperlimits->FanMinimumPwm;
                break;
+       case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
+               od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
+               od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
+               break;
        default:
                od_min_setting = od_max_setting = INT_MAX;
                break;
@@ -1450,6 +1455,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
                                      min_value, max_value);
                break;
 
+       case SMU_OD_FAN_ZERO_RPM_ENABLE:
+               if (!smu_v13_0_0_is_od_feature_supported(smu,
+                                                        PP_OD_FEATURE_ZERO_FAN_BIT))
+                       break;
+
+               size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
+               size += sysfs_emit_at(buf, size, "%d\n",
+                                       (int)od_table->OverDriveTable.FanZeroRpmEnable);
+
+               size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+               smu_v13_0_0_get_od_setting_limits(smu,
+                                                 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+                                                 &min_value,
+                                                 &max_value);
+               size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
+                                     min_value, max_value);
+               break;
+
        case SMU_OD_RANGE:
                if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
                    !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
@@ -1547,6 +1570,11 @@ static int smu_v13_0_0_od_restore_table_single(struct smu_context *smu, long inp
                od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
                od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
                break;
+       case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+               od_table->OverDriveTable.FanZeroRpmEnable =
+                                       boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
+               od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+               break;
        default:
                dev_info(adev->dev, "Invalid table index: %ld\n", input);
                return -EINVAL;
@@ -1840,6 +1868,27 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu,
                od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
                break;
 
+       case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+               if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+                       dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+                       return -ENOTSUPP;
+               }
+
+               smu_v13_0_0_get_od_setting_limits(smu,
+                                                 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+                                                 &minimum,
+                                                 &maximum);
+               if (input[0] < minimum ||
+                   input[0] > maximum) {
+                       dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
+                                input[0], minimum, maximum);
+                       return -EINVAL;
+               }
+
+               od_table->OverDriveTable.FanZeroRpmEnable = input[0];
+               od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+               break;
+
        case PP_OD_RESTORE_DEFAULT_TABLE:
                if (size == 1) {
                        ret = smu_v13_0_0_od_restore_table_single(smu, input[0]);
@@ -2110,7 +2159,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu)
                                            OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
                                            OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
                                            OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
-                                           OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
+                                           OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
+                                           OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
+                                           OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET;
 }
 
 static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
@@ -2176,6 +2227,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
                        user_od_table_bak.OverDriveTable.FanTargetTemperature;
                user_od_table->OverDriveTable.FanMinimumPwm =
                        user_od_table_bak.OverDriveTable.FanMinimumPwm;
+               user_od_table->OverDriveTable.FanZeroRpmEnable =
+                       user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
        }
 
        smu_v13_0_0_set_supported_od_feature_mask(smu);
index 12d622d4aceb00d17fc0ad96f2147d5aa9dfe8bc..1ba2089d865036d35170345d4d84b4cdd72ac821 100644 (file)
@@ -83,6 +83,7 @@
 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET              8
 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE           9
 #define PP_OD_FEATURE_FAN_MINIMUM_PWM                  10
+#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE              11
 
 #define LINK_SPEED_MAX                                 3
 
@@ -1119,6 +1120,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
                od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
                od_max_setting = overdrive_upperlimits->FanMinimumPwm;
                break;
+       case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
+               od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
+               od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
+               break;
        default:
                od_min_setting = od_max_setting = INT_MAX;
                break;
@@ -1439,6 +1444,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
                                      min_value, max_value);
                break;
 
+       case SMU_OD_FAN_ZERO_RPM_ENABLE:
+               if (!smu_v13_0_7_is_od_feature_supported(smu,
+                                                        PP_OD_FEATURE_ZERO_FAN_BIT))
+                       break;
+
+               size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
+               size += sysfs_emit_at(buf, size, "%d\n",
+                                       (int)od_table->OverDriveTable.FanZeroRpmEnable);
+
+               size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+               smu_v13_0_7_get_od_setting_limits(smu,
+                                                 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+                                                 &min_value,
+                                                 &max_value);
+               size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
+                                     min_value, max_value);
+               break;
+
        case SMU_OD_RANGE:
                if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
                    !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
@@ -1535,6 +1558,11 @@ static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long inp
                od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
                od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
                break;
+       case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+               od_table->OverDriveTable.FanZeroRpmEnable =
+                                       boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
+               od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+               break;
        default:
                dev_info(adev->dev, "Invalid table index: %ld\n", input);
                return -EINVAL;
@@ -1828,6 +1856,27 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
                od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
                break;
 
+       case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+               if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+                       dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+                       return -ENOTSUPP;
+               }
+
+               smu_v13_0_7_get_od_setting_limits(smu,
+                                                 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+                                                 &minimum,
+                                                 &maximum);
+               if (input[0] < minimum ||
+                   input[0] > maximum) {
+                       dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
+                                input[0], minimum, maximum);
+                       return -EINVAL;
+               }
+
+               od_table->OverDriveTable.FanZeroRpmEnable = input[0];
+               od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+               break;
+
        case PP_OD_RESTORE_DEFAULT_TABLE:
                if (size == 1) {
                        ret = smu_v13_0_7_od_restore_table_single(smu, input[0]);
@@ -2094,7 +2143,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu)
                                            OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
                                            OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
                                            OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
-                                           OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
+                                           OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
+                                           OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
+                                           OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET;
 }
 
 static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
@@ -2160,6 +2211,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
                        user_od_table_bak.OverDriveTable.FanTargetTemperature;
                user_od_table->OverDriveTable.FanMinimumPwm =
                        user_od_table_bak.OverDriveTable.FanMinimumPwm;
+               user_od_table->OverDriveTable.FanZeroRpmEnable =
+                       user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
        }
 
        smu_v13_0_7_set_supported_od_feature_mask(smu);