]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/pm: fix smu13 power limit range calculation
authorYang Wang <kevinyang.wang@amd.com>
Wed, 1 Jul 2026 01:11:15 +0000 (09:11 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 17:02:15 +0000 (13:02 -0400)
SMU13 reports SocketPowerLimitAc/Dc as the default power limit, but
MsgLimits.Power may carry a different firmware bound for the same PPT
throttler. Using only the socket limit for both min and max can therefore
expose an incorrect power range.

Keep the socket limit as the default, but derive the range from both values:
use the lower value for the min base and the higher value for the max base
before applying OD percentages. Keep the current limit query independent
from the cap calculation.

Fixes: 1eaf26db9590 ("drm/amd/pm: fix smu13 power limit default/cap calculation")
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5419
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 f45bbf0f62f266ed8422d84f347d75d5fca846a7)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c

index 7f8d4bb47d02eb70a278cb3bdbfce94082ea3465..acbd7046d8a50b494c29917714a3f46122871a15 100644 (file)
@@ -2403,11 +2403,14 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
        uint32_t pp_limit = smu->adev->pm.ac_power ?
                              skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
                              skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-       uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+       uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+       uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+       uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+       uint32_t od_percent_upper = 0, od_percent_lower = 0;
        int ret;
 
        if (current_power_limit) {
-               ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+               ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
                if (ret)
                        *current_power_limit = pp_limit;
        }
@@ -2430,12 +2433,12 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
                od_percent_upper, od_percent_lower, pp_limit);
 
        if (max_power_limit) {
-               *max_power_limit = pp_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 = pp_limit * (100 - od_percent_lower);
+               *min_power_limit = min_limit * (100 - od_percent_lower);
                *min_power_limit /= 100;
        }
 
index 0f774b0920ce993c50ae08436b8e7245b7cac0a4..42c9ceeb4f7db3f9d4fb4703b12af4202ec704d6 100644 (file)
@@ -2385,15 +2385,16 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
        uint32_t pp_limit = smu->adev->pm.ac_power ?
                              skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
                              skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-       uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+       uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+       uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+       uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+       uint32_t od_percent_upper = 0, od_percent_lower = 0;
        int ret;
 
        if (current_power_limit) {
-               ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+               ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
                if (ret)
-                       power_limit = pp_limit;
-
-               *current_power_limit = power_limit;
+                       *current_power_limit = pp_limit;
        }
 
        if (default_power_limit)
@@ -2414,12 +2415,12 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
                od_percent_upper, od_percent_lower, pp_limit);
 
        if (max_power_limit) {
-               *max_power_limit = pp_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 = pp_limit * (100 - od_percent_lower);
+               *min_power_limit = min_limit * (100 - od_percent_lower);
                *min_power_limit /= 100;
        }