]> git.ipfire.org Git - thirdparty/kernel/linux.git/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 20:46:13 +0000 (16:46 -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>
(cherry picked from commit c936b8126b444401318fcbeb1828488cc5312dee)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c

index fdc1456b885ce22abceca368b3798ef4bf9bde75..a6a88e7b266857e8b9d6c1f3eeac3504ec43b5ee 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;
        }