[V2 3/8] drm/amd/pm: add fan mode OD setting support for SMU13
Alex Deucher
alexdeucher at gmail.com
Fri Aug 25 13:00:54 UTC 2023
On Thu, Aug 24, 2023 at 10:02 PM Quan, Evan <Evan.Quan at amd.com> wrote:
>
> [AMD Official Use Only - General]
>
> > -----Original Message-----
> > From: Alex Deucher <alexdeucher at gmail.com>
> > Sent: Thursday, August 24, 2023 10:51 PM
> > To: Quan, Evan <Evan.Quan at amd.com>
> > Cc: amd-gfx at lists.freedesktop.org; Deucher, Alexander
> > <Alexander.Deucher at amd.com>
> > Subject: Re: [V2 3/8] drm/amd/pm: add fan mode OD setting support for
> > SMU13
> >
> > On Wed, Aug 23, 2023 at 10:28 PM Quan, Evan <Evan.Quan at amd.com>
> > wrote:
> > >
> > > [AMD Official Use Only - General]
> > >
> > > > -----Original Message-----
> > > > From: Alex Deucher <alexdeucher at gmail.com>
> > > > Sent: Wednesday, August 23, 2023 9:29 PM
> > > > To: Quan, Evan <Evan.Quan at amd.com>
> > > > Cc: amd-gfx at lists.freedesktop.org; Deucher, Alexander
> > > > <Alexander.Deucher at amd.com>
> > > > Subject: Re: [V2 3/8] drm/amd/pm: add fan mode OD setting support
> > > > for
> > > > SMU13
> > > >
> > > > On Wed, Aug 23, 2023 at 2:45 AM Evan Quan <evan.quan at amd.com>
> > > > wrote:
> > > > >
> > > > > Add SMU13 fan mode 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 | 4 +-
> > > > > drivers/gpu/drm/amd/pm/amdgpu_pm.c | 200
> > > > +++++++++++++++++-
> > > > > drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 +
> > > > > 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 | 35 ++-
> > > > > .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 35 ++-
> > > > > 8 files changed, 279 insertions(+), 8 deletions(-)
> > > > >
> > > > > diff --git a/Documentation/gpu/amdgpu/thermal.rst
> > > > > b/Documentation/gpu/amdgpu/thermal.rst
> > > > > index 5e27e4eb3959..8757ec7f0136 100644
> > > > > --- a/Documentation/gpu/amdgpu/thermal.rst
> > > > > +++ b/Documentation/gpu/amdgpu/thermal.rst
> > > > > @@ -64,6 +64,12 @@ gpu_metrics
> > > > > .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
> > > > > :doc: gpu_metrics
> > > > >
> > > > > +fan_mode
> > > > > +--------
> > > > > +
> > > > > +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
> > > > > + :doc: fan_mode
> > > > > +
> > > > > GFXOFF
> > > > > ======
> > > > >
> > > > > diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > > > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > > > index 84c5224d994c..020c9ce1f735 100644
> > > > > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > > > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > > > @@ -113,6 +113,7 @@ enum pp_clock_type {
> > > > > OD_RANGE,
> > > > > OD_VDDGFX_OFFSET,
> > > > > OD_CCLK,
> > > > > + OD_FAN_MODE,
> > > > > };
> > > > >
> > > > > enum amd_pp_sensors {
> > > > > @@ -186,7 +187,8 @@ enum PP_OD_DPM_TABLE_COMMAND {
> > > > > PP_OD_EDIT_VDDC_CURVE,
> > > > > PP_OD_RESTORE_DEFAULT_TABLE,
> > > > > PP_OD_COMMIT_DPM_TABLE,
> > > > > - PP_OD_EDIT_VDDGFX_OFFSET
> > > > > + PP_OD_EDIT_VDDGFX_OFFSET,
> > > > > + PP_OD_EDIT_FAN_MODE,
> > > > > };
> > > > >
> > > > > 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 beb3303fc832..d53d60903fe9 100644
> > > > > --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
> > > > > +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
> > > > > @@ -3383,7 +3383,205 @@ static const struct attribute_group
> > > > *hwmon_groups[] = {
> > > > > NULL
> > > > > };
> > > > >
> > > > > -static struct od_feature_set amdgpu_od_set;
> > > > > +static int amdgpu_retrieve_od_settings(struct amdgpu_device *adev,
> > > > > + enum pp_clock_type od_type,
> > > > > + char *buf) {
> > > > > + int size = 0;
> > > > > + int ret;
> > > > > +
> > > > > + if (amdgpu_in_reset(adev))
> > > > > + return -EPERM;
> > > > > + if (adev->in_suspend && !adev->in_runpm)
> > > > > + return -EPERM;
> > > > > +
> > > > > + ret = pm_runtime_get_sync(adev->dev);
> > > > > + if (ret < 0) {
> > > > > + pm_runtime_put_autosuspend(adev->dev);
> > > > > + return ret;
> > > > > + }
> > > > > +
> > > > > + size = amdgpu_dpm_print_clock_levels(adev, od_type, buf);
> > > > > + if (size == 0)
> > > > > + size = sysfs_emit(buf, "\n");
> > > > > +
> > > > > + pm_runtime_mark_last_busy(adev->dev);
> > > > > + pm_runtime_put_autosuspend(adev->dev);
> > > > > +
> > > > > + return size;
> > > > > +}
> > > > > +
> > > > > +static int parse_input_od_command_lines(const char *buf,
> > > > > + size_t count,
> > > > > + u32 *type,
> > > > > + long *params,
> > > > > + uint32_t *num_of_params) {
> > > > > + const char delimiter[3] = {' ', '\n', '\0'};
> > > > > + uint32_t parameter_size = 0;
> > > > > + char buf_cpy[128] = {0};
> > > > > + char *tmp_str, *sub_str;
> > > > > + int ret;
> > > > > +
> > > > > + if (count > sizeof(buf_cpy) - 1)
> > > > > + return -EINVAL;
> > > > > +
> > > > > + memcpy(buf_cpy, buf, count);
> > > > > + tmp_str = buf_cpy;
> > > > > +
> > > > > + /* skip heading spaces */
> > > > > + while (isspace(*tmp_str))
> > > > > + tmp_str++;
> > > > > +
> > > > > + switch (*tmp_str) {
> > > > > + case 'c':
> > > > > + *type = PP_OD_COMMIT_DPM_TABLE;
> > > > > + return 0;
> > > > > + default:
> > > > > + break;
> > > > > + }
> > > > > +
> > > > > + while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
> > > > > + if (strlen(sub_str) == 0)
> > > > > + continue;
> > > > > +
> > > > > + ret = kstrtol(sub_str, 0, ¶ms[parameter_size]);
> > > > > + if (ret)
> > > > > + return -EINVAL;
> > > > > + parameter_size++;
> > > > > +
> > > > > + while (isspace(*tmp_str))
> > > > > + tmp_str++;
> > > > > + }
> > > > > +
> > > > > + *num_of_params = parameter_size;
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > +static int
> > > > > +amdgpu_distribute_custom_od_settings(struct amdgpu_device *adev,
> > > > > + enum PP_OD_DPM_TABLE_COMMAND cmd_type,
> > > > > + const char *in_buf,
> > > > > + size_t count) {
> > > > > + uint32_t parameter_size = 0;
> > > > > + long parameter[64];
> > > > > + int ret;
> > > > > +
> > > > > + if (amdgpu_in_reset(adev))
> > > > > + return -EPERM;
> > > > > + if (adev->in_suspend && !adev->in_runpm)
> > > > > + return -EPERM;
> > > > > +
> > > > > + ret = parse_input_od_command_lines(in_buf,
> > > > > + count,
> > > > > + &cmd_type,
> > > > > + parameter,
> > > > > + ¶meter_size);
> > > > > + if (ret)
> > > > > + return ret;
> > > > > +
> > > > > + ret = pm_runtime_get_sync(adev->dev);
> > > > > + if (ret < 0)
> > > > > + goto err_out0;
> > > > > +
> > > > > + ret = amdgpu_dpm_odn_edit_dpm_table(adev,
> > > > > + cmd_type,
> > > > > + parameter,
> > > > > + parameter_size);
> > > > > + if (ret)
> > > > > + goto err_out1;
> > > > > +
> > > > > + if (cmd_type == PP_OD_COMMIT_DPM_TABLE) {
> > > > > + ret = amdgpu_dpm_dispatch_task(adev,
> > > > > + AMD_PP_TASK_READJUST_POWER_STATE,
> > > > > + NULL);
> > > > > + if (ret)
> > > > > + goto err_out1;
> > > > > + }
> > > > > +
> > > > > + pm_runtime_mark_last_busy(adev->dev);
> > > > > + pm_runtime_put_autosuspend(adev->dev);
> > > > > +
> > > > > + return count;
> > > > > +
> > > > > +err_out1:
> > > > > + pm_runtime_mark_last_busy(adev->dev);
> > > > > +err_out0:
> > > > > + pm_runtime_put_autosuspend(adev->dev);
> > > > > +
> > > > > + return ret;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * DOC: fan_mode
> > > > > + *
> > > > > + * The amdgpu driver provides a sysfs API for checking and
> > > > > +adjusting the fan
> > > > > + * control mode.
> > > > > + *
> > > > > + * Reading back the file shows you current fan control mode (e.g. '0'
> > > > > +for auto
> > > > > + * mode and '1' for manual mode) and permitted settings if changable.
> > > >
> > > > typo: changeable
> > > >
> > > > Also what does manual vs auto mean in this case? Is the idea that
> > > > you need to switch to manual mode before you make any other
> > > > adjustments (fan curve or
> > > > acoustic) or is this some independent setting?
> > > Auto mode here means PMFW handling the fan speed control in response to
> > the asic temperature. While driver/user can do some fine tuning like acoustic
> > limit/target, fan target-temperature and minimum pwm.
> > > Manual mode here means the fan curve setting specifically. Driver/user can
> > customize how the fan speed in response to the asic temperature.
> > > The two modes are mutually exclusive. Switching to one mode will invalid all
> > those settings installed for the other mode.
> > > Per current implementation for SMU13.0.0 and 13.0.7, user does not need
> > to adjust the fan mode manually. Driver will handle that. For example, on
> > user's setting of fan curve, driver will handle the fan mode switching to manual
> > mode.
> > >
> >
> > If I understand things correctly, the driver will automatically set manual mode
> > if the user adjusts the fan curve? If so, do we need a separate attribute for
> > manual vs automatic? For the documentation, I'd like to see all of the fan
> > options and what sets are required to enable them and what combinations are
> > allowed.
> >
> > 1. temp/pwm fan curve - requires setting manual mode. Mutually exclusive
> > with 2, 3.
> > 2. acoustic targets - requires setting manual mode. Mutually exclusive with 1,
> > 3.
> > 3. temperature targets - requires setting manual mode. Mutually exclusive
> > with 1, 2.
> > 4. minimum fan speed - requires setting manual mode. works with 1,2,3.
> >
> > If the first 3 are mutually exclusive, then maybe we need a fan mode attribute
> > with the following options:
> > 0. auto - let the SMU manage the fan
> > 1. manual - temp/pwm curve
> > 2. manual - acoustic targets
> > 3. manual - temp targets
> [Quan, Evan] No, not such complicated. There are only two fan control mode: auto and manual.
> The settings working under manual mode: temp/pwm curve settings
> The settings working under auto mode: all others (acoustic limit/target, temperature target, minimum pwm...)
> And those settings for auto mode can co-work with each other. They affect the auto fan control via different manners and are not mutually exclusive.
> >
> > If they are not mutually exclusive, then how do they interact? E.g., what
> > happens if you set a custom temp/pwm curve and acoustic targets and they
> > are not compatible? Does that make sense?
> [Quan, Evan] For the sequence above:
> 1. set a custom temp/pwm curve
> - this will switch the fan control to manual mode in order to make the settings to take effect
> - this will invalid all other settings working under auto mode only
> 2. acoustic targets
> - this will switch the fan control to auto mode in order to make the setting to take effect
> - this will invalid the temp/pwm curve settings working under manual mode only
>
Thanks for clarifying. Can you include this information in the
kerneldoc? Also, I think we should either:
1. make the auto/manual required to select enable their respective
subfeatures. (e.g., fail to set the fan curve if auto and vice versa
for the other features)
2. remove the auto/manual attribute and make whatever was last set
take priority.
and document it.
I think 1 is the most obvious from a user perspective, but I don't
have that strong of an opinion.
Alex
> Evan
> >
> > Alex
> >
> >
> >
> > > Please check whether the explanations above make sense to you. I can add
> > them in the code comment part.
> > >
> > > Evan
> > > >
> > > > Alex
> > > >
> > > > > + *
> > > > > + * Writing an integer to the file, sets the fan control mode
> > correspondingly.
> > > > > + *
> > > > > + * When you have finished the editing, write "c" (commit) to the
> > > > > +file to commit
> > > > > + * your changes.
> > > > > + */
> > > > > +static ssize_t fan_mode_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_MODE, buf); }
> > > > > +
> > > > > +static ssize_t fan_mode_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_MODE,
> > > > > + buf,
> > > > > +
> > > > > + count); }
> > > > > +
> > > > > +static umode_t fan_mode_visible(struct amdgpu_device *adev) {
> > > > > + umode_t umode = 0000;
> > > > > +
> > > > > + if (adev->pm.od_feature_mask &
> > > > OD_OPS_SUPPORT_FAN_MODE_RETRIEVE)
> > > > > + umode |= S_IRUSR | S_IRGRP | S_IROTH;
> > > > > +
> > > > > + if (adev->pm.od_feature_mask &
> > OD_OPS_SUPPORT_FAN_MODE_SET)
> > > > > + umode |= S_IWUSR;
> > > > > +
> > > > > + return umode;
> > > > > +}
> > > > > +
> > > > > +static struct od_feature_set amdgpu_od_set = {
> > > > > + .containers = {
> > > > > + [0] = {
> > > > > + .name = "fan_ctrl",
> > > > > + .sub_feature = {
> > > > > + [0] = {
> > > > > + .name = "fan_mode",
> > > > > + .ops = {
> > > > > + .is_visible = fan_mode_visible,
> > > > > + .show = fan_mode_show,
> > > > > + .store = fan_mode_store,
> > > > > + },
> > > > > + },
> > > > > + },
> > > > > + },
> > > > > + },
> > > > > +};
> > > > >
> > > > > static void od_kobj_release(struct kobject *kobj) { diff --git
> > > > > a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> > > > > b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> > > > > index 4cab6a2efb63..b54f84e2408a 100644
> > > > > --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> > > > > +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
> > > > > @@ -314,6 +314,9 @@ struct config_table_setting
> > > > > uint16_t fclk_average_tau; };
> > > > >
> > > > > +#define OD_OPS_SUPPORT_FAN_MODE_RETRIEVE BIT(0)
> > > > > +#define OD_OPS_SUPPORT_FAN_MODE_SET BIT(1)
> > > > > +
> > > > > struct amdgpu_pm {
> > > > > struct mutex mutex;
> > > > > u32 current_sclk;
> > > > > @@ -368,6 +371,7 @@ struct amdgpu_pm {
> > > > > enum amdgpu_runpm_mode rpm_mode;
> > > > >
> > > > > struct list_head od_kobj_list;
> > > > > + uint32_t od_feature_mask;
> > > > > };
> > > > >
> > > > > int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum
> > > > > amd_pp_sensors sensor, diff --git
> > > > > a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> > > > > b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> > > > > index f005a90c35af..01ccfd219d6b 100644
> > > > > --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> > > > > +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> > > > > @@ -2481,6 +2481,8 @@ static enum smu_clk_type
> > > > smu_convert_to_smuclk(enum pp_clock_type type)
> > > > > clk_type = SMU_OD_VDDGFX_OFFSET; break;
> > > > > case OD_CCLK:
> > > > > clk_type = SMU_OD_CCLK; break;
> > > > > + case OD_FAN_MODE:
> > > > > + clk_type = SMU_OD_FAN_MODE; 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 e57265cf637c..498000850212 100644
> > > > > --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> > > > > +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
> > > > > @@ -280,6 +280,7 @@ enum smu_clk_type {
> > > > > SMU_OD_VDDC_CURVE,
> > > > > SMU_OD_RANGE,
> > > > > SMU_OD_VDDGFX_OFFSET,
> > > > > + SMU_OD_FAN_MODE,
> > > > > 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 1041ba22f8f8..45b42e43f9a3 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
> > > > > @@ -101,6 +101,7 @@
> > > > > #define PP_OD_FEATURE_UCLK_FMIN 2
> > > > > #define PP_OD_FEATURE_UCLK_FMAX 3
> > > > > #define PP_OD_FEATURE_GFX_VF_CURVE 4
> > > > > +#define PP_OD_FEATURE_FAN_MODE 5
> > > > >
> > > > > #define LINK_SPEED_MAX 3
> > > > >
> > > > > @@ -1110,6 +1111,10 @@ static void
> > > > smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
> > > > > od_min_setting = overdrive_lowerlimits-
> > > > >VoltageOffsetPerZoneBoundary;
> > > > > od_max_setting = overdrive_upperlimits-
> > > > >VoltageOffsetPerZoneBoundary;
> > > > > break;
> > > > > + case PP_OD_FEATURE_FAN_MODE:
> > > > > + od_min_setting = overdrive_lowerlimits->FanMode;
> > > > > + od_max_setting = overdrive_upperlimits->FanMode;
> > > > > + break;
> > > > > default:
> > > > > od_min_setting = od_max_setting = INT_MAX;
> > > > > break;
> > > > > @@ -1329,6 +1334,16 @@ static int
> > > > > smu_v13_0_0_print_clk_levels(struct
> > > > smu_context *smu,
> > > > > od_table-
> > > > >OverDriveTable.VoltageOffsetPerZoneBoundary[0]);
> > > > > break;
> > > > >
> > > > > + case SMU_OD_FAN_MODE:
> > > > > + if (!smu_v13_0_0_is_od_feature_supported(smu,
> > > > > + PP_OD_FEATURE_FAN_CURVE_BIT))
> > > > > + break;
> > > > > +
> > > > > + size += sysfs_emit_at(buf, size, "OD_FAN_MODE:\n");
> > > > > + size += sysfs_emit_at(buf, size, "%d\n",
> > > > > + (int)od_table->OverDriveTable.FanMode);
> > > > > + 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) && @@ -1789,6 +1804,15 @@ static
> > ssize_t
> > > > smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
> > > > > return sizeof(struct gpu_metrics_v1_3); }
> > > > >
> > > > > +static void smu_v13_0_0_set_supported_od_feature_mask(struct
> > > > > +smu_context *smu) {
> > > > > + struct amdgpu_device *adev = smu->adev;
> > > > > +
> > > > > + if (smu_v13_0_0_is_od_feature_supported(smu,
> > > > > + PP_OD_FEATURE_FAN_CURVE_BIT))
> > > > > + adev->pm.od_feature_mask |=
> > > > > +OD_OPS_SUPPORT_FAN_MODE_RETRIEVE; }
> > > > > +
> > > > > static int smu_v13_0_0_set_default_od_settings(struct smu_context
> > > > > *smu) {
> > > > > OverDriveTableExternal_t *od_table = @@ -1838,8 +1862,12
> > > > >@@ static int smu_v13_0_0_set_default_od_settings(struct
> > smu_context *smu)
> > > > > for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
> > > > > user_od_table-
> > > > >OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
> > > > >
> > > > > user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
> > > > > + user_od_table->OverDriveTable.FanMode =
> > > > > + user_od_table_bak.OverDriveTable.FanMode;
> > > > > }
> > > > >
> > > > > + smu_v13_0_0_set_supported_od_feature_mask(smu);
> > > > > +
> > > > > return 0;
> > > > > }
> > > > >
> > > > > @@ -1850,9 +1878,10 @@ static int
> > > > smu_v13_0_0_restore_user_od_settings(struct smu_context *smu)
> > > > > OverDriveTableExternal_t *user_od_table = table_context-
> > > > >user_overdrive_table;
> > > > > int res;
> > > > >
> > > > > - user_od_table->OverDriveTable.FeatureCtrlMask = 1U <<
> > > > PP_OD_FEATURE_GFXCLK_BIT |
> > > > > - 1U << PP_OD_FEATURE_UCLK_BIT |
> > > > > - 1U <<
> > PP_OD_FEATURE_GFX_VF_CURVE_BIT;
> > > > > + user_od_table->OverDriveTable.FeatureCtrlMask =
> > > > BIT(PP_OD_FEATURE_GFXCLK_BIT) |
> > > > > + BIT(PP_OD_FEATURE_UCLK_BIT) |
> > > > > +
> > > > > + BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) |
> > > > > +
> > > > > + BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> > > > > res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table);
> > > > > user_od_table->OverDriveTable.FeatureCtrlMask = 0;
> > > > > if (res == 0)
> > > > > 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 328765f89c94..28c2e4b0e55d 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
> > > > > @@ -77,6 +77,7 @@
> > > > > #define PP_OD_FEATURE_UCLK_FMIN 2
> > > > > #define PP_OD_FEATURE_UCLK_FMAX 3
> > > > > #define PP_OD_FEATURE_GFX_VF_CURVE 4
> > > > > +#define PP_OD_FEATURE_FAN_MODE 5
> > > > >
> > > > > #define LINK_SPEED_MAX 3
> > > > >
> > > > > @@ -1096,6 +1097,10 @@ static void
> > > > smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
> > > > > od_min_setting = overdrive_lowerlimits-
> > > > >VoltageOffsetPerZoneBoundary;
> > > > > od_max_setting = overdrive_upperlimits-
> > > > >VoltageOffsetPerZoneBoundary;
> > > > > break;
> > > > > + case PP_OD_FEATURE_FAN_MODE:
> > > > > + od_min_setting = overdrive_lowerlimits->FanMode;
> > > > > + od_max_setting = overdrive_upperlimits->FanMode;
> > > > > + break;
> > > > > default:
> > > > > od_min_setting = od_max_setting = INT_MAX;
> > > > > break;
> > > > > @@ -1315,6 +1320,16 @@ static int
> > > > > smu_v13_0_7_print_clk_levels(struct
> > > > smu_context *smu,
> > > > > od_table-
> > > > >OverDriveTable.VoltageOffsetPerZoneBoundary[0]);
> > > > > break;
> > > > >
> > > > > + case SMU_OD_FAN_MODE:
> > > > > + if (!smu_v13_0_7_is_od_feature_supported(smu,
> > > > > + PP_OD_FEATURE_FAN_CURVE_BIT))
> > > > > + break;
> > > > > +
> > > > > + size += sysfs_emit_at(buf, size, "OD_FAN_MODE:\n");
> > > > > + size += sysfs_emit_at(buf, size, "%d\n",
> > > > > + (int)od_table->OverDriveTable.FanMode);
> > > > > + 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) && @@ -1770,6 +1785,15 @@ static
> > ssize_t
> > > > smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
> > > > > return sizeof(struct gpu_metrics_v1_3); }
> > > > >
> > > > > +static void smu_v13_0_7_set_supported_od_feature_mask(struct
> > > > > +smu_context *smu) {
> > > > > + struct amdgpu_device *adev = smu->adev;
> > > > > +
> > > > > + if (smu_v13_0_7_is_od_feature_supported(smu,
> > > > > + PP_OD_FEATURE_FAN_CURVE_BIT))
> > > > > + adev->pm.od_feature_mask |=
> > > > > +OD_OPS_SUPPORT_FAN_MODE_RETRIEVE; }
> > > > > +
> > > > > static int smu_v13_0_7_set_default_od_settings(struct smu_context
> > > > > *smu) {
> > > > > OverDriveTableExternal_t *od_table = @@ -1819,8 +1843,12
> > > > >@@ static int smu_v13_0_7_set_default_od_settings(struct
> > smu_context *smu)
> > > > > for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
> > > > > user_od_table-
> > > > >OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
> > > > >
> > > > > user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
> > > > > + user_od_table->OverDriveTable.FanMode =
> > > > > + user_od_table_bak.OverDriveTable.FanMode;
> > > > > }
> > > > >
> > > > > + smu_v13_0_7_set_supported_od_feature_mask(smu);
> > > > > +
> > > > > return 0;
> > > > > }
> > > > >
> > > > > @@ -1831,9 +1859,10 @@ static int
> > > > smu_v13_0_7_restore_user_od_settings(struct smu_context *smu)
> > > > > OverDriveTableExternal_t *user_od_table = table_context-
> > > > >user_overdrive_table;
> > > > > int res;
> > > > >
> > > > > - user_od_table->OverDriveTable.FeatureCtrlMask = 1U <<
> > > > PP_OD_FEATURE_GFXCLK_BIT |
> > > > > - 1U << PP_OD_FEATURE_UCLK_BIT |
> > > > > - 1U <<
> > PP_OD_FEATURE_GFX_VF_CURVE_BIT;
> > > > > + user_od_table->OverDriveTable.FeatureCtrlMask =
> > > > BIT(PP_OD_FEATURE_GFXCLK_BIT) |
> > > > > + BIT(PP_OD_FEATURE_UCLK_BIT) |
> > > > > +
> > > > > + BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) |
> > > > > +
> > > > > + BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
> > > > > res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table);
> > > > > user_od_table->OverDriveTable.FeatureCtrlMask = 0;
> > > > > if (res == 0)
> > > > > --
> > > > > 2.34.1
> > > > >
More information about the amd-gfx
mailing list