[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

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