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 <[email protected]>
---
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 28 +++++++++++--------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index edc5140f6ab6..b8584a1e6bcc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1622,19 +1622,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 &&
@@ -1648,15 +1652,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;
        }
 
-- 
2.47.3

Reply via email to