On Wed, Aug 23, 2023 at 10:28 PM Quan, Evan <Evan.Quan@xxxxxxx> wrote: > > [AMD Official Use Only - General] > > > -----Original Message----- > > From: Alex Deucher <alexdeucher@xxxxxxxxx> > > Sent: Wednesday, August 23, 2023 9:29 PM > > To: Quan, Evan <Evan.Quan@xxxxxxx> > > Cc: amd-gfx@xxxxxxxxxxxxxxxxxxxxx; Deucher, Alexander > > <Alexander.Deucher@xxxxxxx> > > 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@xxxxxxx> > > wrote: > > > > > > Add SMU13 fan mode OD setting support. > > > > > > Signed-off-by: Evan Quan <evan.quan@xxxxxxx> > > > -- > > > 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 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? 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 > > >