]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/pm: fix smu13 power limit default/cap calculation
authorYang Wang <kevinyang.wang@amd.com>
Tue, 19 May 2026 03:18:12 +0000 (11:18 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 3 Jun 2026 18:50:58 +0000 (14:50 -0400)
smu_v13_0_0_get_power_limit() and smu_v13_0_7_get_power_limit() mix
runtime power_limit with PP table limits when reporting default/min/max.

When current power limit query succeeds, default_power_limit was set to the
runtime value instead of the PP table default, and min/max could be derived
from inconsistent bases (MsgLimits/runtime), leading to incorrect cap info.

Use SocketPowerLimitAc/Dc as the PP default base (pp_limit), keep
current_power_limit as runtime value, and derive min/max from pp_limit with
OD percentages.

Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5227
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 1eaf26db95901ca70737503a89b831dd763c8453)
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 fa861ec4d7003ece6452110c238cd06384cd30b7..7f8d4bb47d02eb70a278cb3bdbfce94082ea3465 100644 (file)
@@ -2390,28 +2390,30 @@ static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu)
 }
 
 static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
-                                               uint32_t *current_power_limit,
-                                               uint32_t *default_power_limit,
-                                               uint32_t *max_power_limit,
-                                               uint32_t *min_power_limit)
+                                      uint32_t *current_power_limit,
+                                      uint32_t *default_power_limit,
+                                      uint32_t *max_power_limit,
+                                      uint32_t *min_power_limit)
 {
        struct smu_table_context *table_context = &smu->smu_table;
        struct smu_13_0_0_powerplay_table *powerplay_table =
                (struct smu_13_0_0_powerplay_table *)table_context->power_play_table;
        PPTable_t *pptable = table_context->driver_pptable;
        SkuTable_t *skutable = &pptable->SkuTable;
-       uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
-       uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-
-       if (smu_v13_0_get_current_power_limit(smu, &power_limit))
-               power_limit = smu->adev->pm.ac_power ?
+       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;
+       int ret;
+
+       if (current_power_limit) {
+               ret = smu_v13_0_get_current_power_limit(smu, &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 &&
@@ -2425,15 +2427,15 @@ static int smu_v13_0_0_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 = pp_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 = pp_limit * (100 - od_percent_lower);
                *min_power_limit /= 100;
        }
 
index 5abf2b0703c6210520d4ef4a16b55f85b9260cbc..0f774b0920ce993c50ae08436b8e7245b7cac0a4 100644 (file)
@@ -2372,28 +2372,32 @@ static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
 }
 
 static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
-                                               uint32_t *current_power_limit,
-                                               uint32_t *default_power_limit,
-                                               uint32_t *max_power_limit,
-                                               uint32_t *min_power_limit)
+                                      uint32_t *current_power_limit,
+                                      uint32_t *default_power_limit,
+                                      uint32_t *max_power_limit,
+                                      uint32_t *min_power_limit)
 {
        struct smu_table_context *table_context = &smu->smu_table;
        struct smu_13_0_7_powerplay_table *powerplay_table =
                (struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
        PPTable_t *pptable = table_context->driver_pptable;
        SkuTable_t *skutable = &pptable->SkuTable;
-       uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
-       uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-
-       if (smu_v13_0_get_current_power_limit(smu, &power_limit))
-               power_limit = smu->adev->pm.ac_power ?
+       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;
+       int ret;
+
+       if (current_power_limit) {
+               ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+               if (ret)
+                       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 &&
@@ -2407,15 +2411,15 @@ static int smu_v13_0_7_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 = pp_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 = pp_limit * (100 - od_percent_lower);
                *min_power_limit /= 100;
        }