]> git.hungrycats.org Git - linux/commitdiff
drm/amd/pm: fix smu14 power limit range calculation
authorYang Wang <kevinyang.wang@amd.com>
Mon, 6 Jul 2026 01:29:24 +0000 (09:29 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 8 Jul 2026 18:25:32 +0000 (14:25 -0400)
SMU14 derives the default PPT limit from SocketPowerLimitAc/Dc, but
MsgLimits.Power may expose a different firmware limit for the same PPT0
throttler. Using those values independently as fixed min/max bases can
report an incorrect configurable power range.

Keep the socket power limit as the default value and as the fallback for
current-limit queries. Calculate the reported range from both firmware
values instead, using the lower value as the minimum base and the higher
value as the maximum base before applying OD percentages.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c

index d6cf643205abc22a0e82bc1c089476e61d582d21..0fbcaf884419dedad96c2766fcc3e99114f58c6e 100644 (file)
@@ -1621,19 +1621,23 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
                table_context->power_play_table;
        PPTable_t *pptable = table_context->driver_pptable;
        CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
-       int16_t od_percent_upper = 0, od_percent_lower = 0;
+       uint32_t pp_limit = smu->adev->pm.ac_power ?
+               skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+               skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
        uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-       uint32_t power_limit;
+       uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+       uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+       int16_t od_percent_upper = 0, od_percent_lower = 0;
+       int ret;
 
-       if (smu_v14_0_get_current_power_limit(smu, &power_limit))
-               power_limit = smu->adev->pm.ac_power ?
-                             skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-                             skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+       if (current_power_limit) {
+               ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
+               if (ret)
+                       *current_power_limit = pp_limit;
+       }
 
-       if (current_power_limit)
-               *current_power_limit = power_limit;
        if (default_power_limit)
-               *default_power_limit = power_limit;
+               *default_power_limit = pp_limit;
 
        if (powerplay_table) {
                if (smu->od_enabled &&
@@ -1647,15 +1651,15 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
        }
 
        dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-                                       od_percent_upper, od_percent_lower, power_limit);
+                                       od_percent_upper, od_percent_lower, pp_limit);
 
        if (max_power_limit) {
-               *max_power_limit = msg_limit * (100 + od_percent_upper);
+               *max_power_limit = max_limit * (100 + od_percent_upper);
                *max_power_limit /= 100;
        }
 
        if (min_power_limit) {
-               *min_power_limit = power_limit * (100 + od_percent_lower);
+               *min_power_limit = min_limit * (100 + od_percent_lower);
                *min_power_limit /= 100;
        }