AMD General

msg_limit is still valid, but it's ok to set max_power_limit based on the 
default limit.
Reviewed-by: Kenneth Feng <[email protected]>


-----Original Message-----
From: Wang, Yang(Kevin) <[email protected]>
Sent: Tuesday, May 19, 2026 12:18 PM
To: [email protected]
Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking 
<[email protected]>; Feng, Kenneth <[email protected]>
Subject: [PATCH] drm/amd/pm: fix smu13 power limit default/cap calculation

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 <[email protected]>
---
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 32 +++++++++++--------  
.../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 32 +++++++++++--------
 2 files changed, 36 insertions(+), 28 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 30d9cfac0d89..9e74a5c4be43 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
@@ -2391,28 +2391,32 @@ 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)
+                       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 &&
@@ -2426,15 +2430,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;
        }

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 d253ce367476..481908913dde 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
@@ -2373,28 +2373,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 &&
@@ -2408,15 +2412,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;
        }

--
2.47.3

Reply via email to