mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
drm/amd/pm: fix smu14 power limit range calculation
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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user