On Thu, Mar 19, 2026 at 11:24 PM Wang, Yang(Kevin)
<[email protected]> wrote:
>
> [AMD Official Use Only - AMD Internal Distribution Only]
>
> Extra information:
>
> [Issue]: Can not set fan speed on Radeon Pro W7900
> Closes: https://github.com/ROCm/amdgpu/issues/208

With that line added to the commit,
Acked-by: Alex Deucher <[email protected]>

>
> Best Regards,
> Kevin
>
> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of Yang Wang
> Sent: Friday, March 20, 2026 09:48
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking 
> <[email protected]>; Feng, Kenneth <[email protected]>
> Subject: [PATCH 1/2] drm/amd/pm: disable OD_FAN_CURVE if temp or pwm range 
> invalid for smu v13
>
> Forcibly disable the OD_FAN_CURVE feature when temperature or PWM range is 
> invalid, otherwise PMFW will reject this configuration on smu v13.0.x
>
> example:
> $ sudo cat /sys/bus/pci/devices/<BDF>/gpu_od/fan_ctrl/fan_curve
>
> OD_FAN_CURVE:
> 0: 0C 0%
> 1: 0C 0%
> 2: 0C 0%
> 3: 0C 0%
> 4: 0C 0%
> OD_RANGE:
> FAN_CURVE(hotspot temp): 0C 0C
> FAN_CURVE(fan speed): 0% 0%
>
> $ echo "0 50 40" | sudo tee fan_curve
>
> kernel log:
> [  756.442527] amdgpu 0000:03:00.0: amdgpu: Fan curve temp setting(50) must 
> be within [0, 0]!
> [  777.345800] amdgpu 0000:03:00.0: amdgpu: Fan curve temp setting(50) must 
> be within [0, 0]!
>
> Signed-off-by: Yang Wang <[email protected]>
> ---
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 33 ++++++++++++++++++-  
> .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 33 ++++++++++++++++++-
>  2 files changed, 64 insertions(+), 2 deletions(-)
>
> 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 cd077151f3e4..9be7a2af560d 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
> @@ -59,6 +59,10 @@
>
>  #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, 
> pm.smu_i2c))
>
> +static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
> +                                             int od_feature_bit,
> +                                             int32_t *min, int32_t *max);
> +
>  static const struct smu_feature_bits smu_v13_0_0_dpm_features = {
>         .bits = {
>                 SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
> @@ -1044,8 +1048,35 @@ static bool smu_v13_0_0_is_od_feature_supported(struct 
> smu_context *smu,
>         PPTable_t *pptable = smu->smu_table.driver_pptable;
>         const OverDriveLimits_t * const overdrive_upperlimits =
>                                 &pptable->SkuTable.OverDriveLimitsBasicMax;
> +       int32_t min_value, max_value;
> +       bool feature_enabled;
>
> -       return overdrive_upperlimits->FeatureCtrlMask & (1U << 
> od_feature_bit);
> +       switch (od_feature_bit) {
> +       case PP_OD_FEATURE_FAN_CURVE_BIT:
> +               feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & 
> (1U << od_feature_bit));
> +               if (feature_enabled) {
> +                       smu_v13_0_0_get_od_setting_limits(smu, 
> PP_OD_FEATURE_FAN_CURVE_TEMP,
> +                                                         &min_value, 
> &max_value);
> +                       if (!min_value && !max_value) {
> +                               feature_enabled = false;
> +                               goto out;
> +                       }
> +
> +                       smu_v13_0_0_get_od_setting_limits(smu, 
> PP_OD_FEATURE_FAN_CURVE_PWM,
> +                                                         &min_value, 
> &max_value);
> +                       if (!min_value && !max_value) {
> +                               feature_enabled = false;
> +                               goto out;
> +                       }
> +               }
> +               break;
> +       default:
> +               feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & 
> (1U << od_feature_bit));
> +               break;
> +       }
> +
> +out:
> +       return feature_enabled;
>  }
>
>  static void smu_v13_0_0_get_od_setting_limits(struct smu_context *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 a1d50654db72..5cc15545da6e 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
> @@ -59,6 +59,10 @@
>
>  #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, 
> pm.smu_i2c))
>
> +static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
> +                                             int od_feature_bit,
> +                                             int32_t *min, int32_t *max);
> +
>  static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
>         .bits = {
>                 SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
> @@ -1054,8 +1058,35 @@ static bool smu_v13_0_7_is_od_feature_supported(struct 
> smu_context *smu,
>         PPTable_t *pptable = smu->smu_table.driver_pptable;
>         const OverDriveLimits_t * const overdrive_upperlimits =
>                                 &pptable->SkuTable.OverDriveLimitsBasicMax;
> +       int32_t min_value, max_value;
> +       bool feature_enabled;
>
> -       return overdrive_upperlimits->FeatureCtrlMask & (1U << 
> od_feature_bit);
> +       switch (od_feature_bit) {
> +       case PP_OD_FEATURE_FAN_CURVE_BIT:
> +               feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & 
> (1U << od_feature_bit));
> +               if (feature_enabled) {
> +                       smu_v13_0_7_get_od_setting_limits(smu, 
> PP_OD_FEATURE_FAN_CURVE_TEMP,
> +                                                         &min_value, 
> &max_value);
> +                       if (!min_value && !max_value) {
> +                               feature_enabled = false;
> +                               goto out;
> +                       }
> +
> +                       smu_v13_0_7_get_od_setting_limits(smu, 
> PP_OD_FEATURE_FAN_CURVE_PWM,
> +                                                         &min_value, 
> &max_value);
> +                       if (!min_value && !max_value) {
> +                               feature_enabled = false;
> +                               goto out;
> +                       }
> +               }
> +               break;
> +       default:
> +               feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & 
> (1U << od_feature_bit));
> +               break;
> +       }
> +
> +out:
> +       return feature_enabled;
>  }
>
>  static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
> --
> 2.47.3
>

Reply via email to