Skip to content

Commit

Permalink
drm/amd/pm: add zero RPM OD setting support for SMU13
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Wolfgang Müller authored and Alex Deucher committed Nov 5, 2024
1 parent 8cc438b commit cfffd98
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Documentation/gpu/amdgpu/thermal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
======

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/include/kgd_pp_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
62 changes: 62 additions & 0 deletions drivers/gpu/drm/amd/pm/amdgpu_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand Down Expand Up @@ -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,
},
},
},
},
},
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down
55 changes: 54 additions & 1 deletion drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) &&
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
55 changes: 54 additions & 1 deletion drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) &&
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit cfffd98

Please sign in to comment.