[V2 8/8] drm/amd/pm: add fan minimum pwm OD setting support for SMU13
Alex Deucher
alexdeucher at gmail.com
Wed Aug 23 13:34:13 UTC 2023
Are there any restrictions on which fan control options you can
enable? I.e., can you mess with all of these or are there several
discrete fan modes (acoustic, curve, min fan, etc.) that you have to
set up independently? We should document the restrictions.
Alex
On Wed, Aug 23, 2023 at 2:45 AM Evan Quan <evan.quan at amd.com> wrote:
>
> Add SMU13 fan minimum pwm OD setting support.
>
> Signed-off-by: Evan Quan <evan.quan at amd.com>
> --
> v1->v2:
> - add missing kerneldoc for the new interface(Alex)
> ---
> Documentation/gpu/amdgpu/thermal.rst | 6 ++
> .../gpu/drm/amd/include/kgd_pp_interface.h | 2 +
> drivers/gpu/drm/amd/pm/amdgpu_pm.c | 59 +++++++++++++++++++
> drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 +
> drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +
> drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 +
> .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 51 +++++++++++++++-
> .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 51 +++++++++++++++-
> 8 files changed, 172 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst
> index 073ab9e418b1..940f723472b8 100644
> --- a/Documentation/gpu/amdgpu/thermal.rst
> +++ b/Documentation/gpu/amdgpu/thermal.rst
> @@ -94,6 +94,12 @@ fan_target_temperature
> .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
> :doc: fan_target_temperature
>
> +fan_minimum_pwm
> +---------------
> +
> +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
> + :doc: fan_minimum_pwm
> +
> GFXOFF
> ======
>
> diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> index c1065136f527..528c892f7c4b 100644
> --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> @@ -118,6 +118,7 @@ enum pp_clock_type {
> OD_ACOUSTIC_LIMIT,
> OD_ACOUSTIC_TARGET,
> OD_FAN_TARGET_TEMPERATURE,
> + OD_FAN_MINIMUM_PWM,
> };
>
> enum amd_pp_sensors {
> @@ -197,6 +198,7 @@ enum PP_OD_DPM_TABLE_COMMAND {
> PP_OD_EDIT_ACOUSTIC_LIMIT,
> PP_OD_EDIT_ACOUSTIC_TARGET,
> PP_OD_EDIT_FAN_TARGET_TEMPERATURE,
> + PP_OD_EDIT_FAN_MINIMUM_PWM,
> };
>
> struct pp_states_info {
> diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
> index 682eef0c0eeb..fa6c4ab16ccf 100644
> --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
> +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
> @@ -3772,6 +3772,57 @@ static umode_t fan_target_temperature_visible(struct amdgpu_device *adev)
> return umode;
> }
>
> +/**
> + * DOC: fan_minimum_pwm
> + *
> + * The amdgpu driver provides a sysfs API for checking and adjusting the
> + * minimum fan speed in PWM.
> + *
> + * 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. NOTE: this will switch the fan control to auto mode.
> + */
> +static ssize_t fan_minimum_pwm_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_MINIMUM_PWM, buf);
> +}
> +
> +static ssize_t fan_minimum_pwm_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_MINIMUM_PWM,
> + buf,
> + count);
> +}
> +
> +static umode_t fan_minimum_pwm_visible(struct amdgpu_device *adev)
> +{
> + umode_t umode = 0000;
> +
> + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE)
> + umode |= S_IRUSR | S_IRGRP | S_IROTH;
> +
> + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET)
> + umode |= S_IWUSR;
> +
> + return umode;
> +}
> +
> static struct od_feature_set amdgpu_od_set = {
> .containers = {
> [0] = {
> @@ -3817,6 +3868,14 @@ static struct od_feature_set amdgpu_od_set = {
> .store = fan_target_temperature_store,
> },
> },
> + [5] = {
> + .name = "fan_minimum_pwm",
> + .ops = {
> + .is_visible = fan_minimum_pwm_visible,
> + .show = fan_minimum_pwm_show,
> + .store = fan_minimum_pwm_store,
> + },
> + },
> },
> },
> },
> diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> index 80d2ac1ecb9f..342c4d8318dc 100644
> --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> @@ -324,6 +324,8 @@ struct config_table_setting
> #define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET BIT(7)
> #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE BIT(8)
> #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET BIT(9)
> +#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE BIT(10)
> +#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET BIT(11)
>
> struct amdgpu_pm {
> struct mutex mutex;
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> index 22a6527139a6..d22ed5a272ce 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> @@ -2491,6 +2491,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
> clk_type = SMU_OD_ACOUSTIC_TARGET; break;
> case OD_FAN_TARGET_TEMPERATURE:
> clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break;
> + case OD_FAN_MINIMUM_PWM:
> + clk_type = SMU_OD_FAN_MINIMUM_PWM; break;
> default:
> clk_type = SMU_CLK_COUNT; break;
> }
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> index 1a00f807fb09..5c8f30f600f8 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> @@ -285,6 +285,7 @@ enum smu_clk_type {
> SMU_OD_ACOUSTIC_LIMIT,
> SMU_OD_ACOUSTIC_TARGET,
> SMU_OD_FAN_TARGET_TEMPERATURE,
> + SMU_OD_FAN_MINIMUM_PWM,
> SMU_CLK_COUNT,
> };
>
> 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 953620f95abc..bedd9ca3605c 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
> @@ -107,6 +107,7 @@
> #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 8
> #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 9
> #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 10
> +#define PP_OD_FEATURE_FAN_MINIMUM_PWM 11
>
> #define LINK_SPEED_MAX 3
>
> @@ -1140,6 +1141,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
> od_min_setting = overdrive_lowerlimits->FanTargetTemperature;
> od_max_setting = overdrive_upperlimits->FanTargetTemperature;
> break;
> + case PP_OD_FEATURE_FAN_MINIMUM_PWM:
> + od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
> + od_max_setting = overdrive_upperlimits->FanMinimumPwm;
> + break;
> default:
> od_min_setting = od_max_setting = INT_MAX;
> break;
> @@ -1452,6 +1457,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
> min_value, max_value);
> break;
>
> + case SMU_OD_FAN_MINIMUM_PWM:
> + if (!smu_v13_0_0_is_od_feature_supported(smu,
> + PP_OD_FEATURE_FAN_CURVE_BIT))
> + break;
> +
> + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n");
> + size += sysfs_emit_at(buf, size, "%d\n",
> + (int)od_table->OverDriveTable.FanMinimumPwm);
> +
> + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
> + smu_v13_0_0_get_od_setting_limits(smu,
> + PP_OD_FEATURE_FAN_MINIMUM_PWM,
> + &min_value,
> + &max_value);
> + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %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) &&
> @@ -1766,6 +1789,28 @@ 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_MINIMUM_PWM:
> + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
> + dev_warn(adev->dev, "Fan curve setting not supported!\n");
> + return -ENOTSUPP;
> + }
> +
> + smu_v13_0_0_get_od_setting_limits(smu,
> + PP_OD_FEATURE_FAN_MINIMUM_PWM,
> + &minimum,
> + &maximum);
> + if (input[0] < minimum ||
> + input[0] > maximum) {
> + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n",
> + input[0], minimum, maximum);
> + return -EINVAL;
> + }
> +
> + od_table->OverDriveTable.FanMinimumPwm = input[0];
> + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> + break;
> +
> case PP_OD_RESTORE_DEFAULT_TABLE:
> feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
> memcpy(od_table,
> @@ -2030,7 +2075,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu)
> OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE |
> OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET |
> OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
> - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET;
> + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
> + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
> + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
> }
>
> static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
> @@ -2096,6 +2143,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
> user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold;
> user_od_table->OverDriveTable.FanTargetTemperature =
> user_od_table_bak.OverDriveTable.FanTargetTemperature;
> + user_od_table->OverDriveTable.FanMinimumPwm =
> + user_od_table_bak.OverDriveTable.FanMinimumPwm;
> }
>
> smu_v13_0_0_set_supported_od_feature_mask(smu);
> 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 a4d48ef5aaa7..c2ca5f228dd5 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
> @@ -83,6 +83,7 @@
> #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 8
> #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 9
> #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 10
> +#define PP_OD_FEATURE_FAN_MINIMUM_PWM 11
>
> #define LINK_SPEED_MAX 3
>
> @@ -1126,6 +1127,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
> od_min_setting = overdrive_lowerlimits->FanTargetTemperature;
> od_max_setting = overdrive_upperlimits->FanTargetTemperature;
> break;
> + case PP_OD_FEATURE_FAN_MINIMUM_PWM:
> + od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
> + od_max_setting = overdrive_upperlimits->FanMinimumPwm;
> + break;
> default:
> od_min_setting = od_max_setting = INT_MAX;
> break;
> @@ -1438,6 +1443,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
> min_value, max_value);
> break;
>
> + case SMU_OD_FAN_MINIMUM_PWM:
> + if (!smu_v13_0_7_is_od_feature_supported(smu,
> + PP_OD_FEATURE_FAN_CURVE_BIT))
> + break;
> +
> + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n");
> + size += sysfs_emit_at(buf, size, "%d\n",
> + (int)od_table->OverDriveTable.FanMinimumPwm);
> +
> + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
> + smu_v13_0_7_get_od_setting_limits(smu,
> + PP_OD_FEATURE_FAN_MINIMUM_PWM,
> + &min_value,
> + &max_value);
> + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %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) &&
> @@ -1752,6 +1775,28 @@ 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_MINIMUM_PWM:
> + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
> + dev_warn(adev->dev, "Fan curve setting not supported!\n");
> + return -ENOTSUPP;
> + }
> +
> + smu_v13_0_7_get_od_setting_limits(smu,
> + PP_OD_FEATURE_FAN_MINIMUM_PWM,
> + &minimum,
> + &maximum);
> + if (input[0] < minimum ||
> + input[0] > maximum) {
> + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n",
> + input[0], minimum, maximum);
> + return -EINVAL;
> + }
> +
> + od_table->OverDriveTable.FanMinimumPwm = input[0];
> + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
> + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> + break;
> +
> case PP_OD_RESTORE_DEFAULT_TABLE:
> feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
> memcpy(od_table,
> @@ -2011,7 +2056,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu)
> OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE |
> OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET |
> OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
> - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET;
> + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
> + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
> + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
> }
>
> static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
> @@ -2077,6 +2124,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
> user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold;
> user_od_table->OverDriveTable.FanTargetTemperature =
> user_od_table_bak.OverDriveTable.FanTargetTemperature;
> + user_od_table->OverDriveTable.FanMinimumPwm =
> + user_od_table_bak.OverDriveTable.FanMinimumPwm;
> }
>
> smu_v13_0_7_set_supported_od_feature_mask(smu);
> --
> 2.34.1
>
More information about the amd-gfx
mailing list