[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, &params[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,
> > > > > +                                          &parameter_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