drm/amd/pm: derive stable PPT limits from PPTable

GetPptLimit reports mutable PMFW runtime state. Using that value for
static capabilities causes two externally visible problems:

- A userspace override changes the default reported through hwmon.
- A firmware reset changes the advertised minimum or maximum range.

Derive platform defaults and supported ranges from the driver PPTable
for Sienna Cichlid, Navi10, Arcturus, and Aldebaran. Reserve PMFW queries
for the effective current limit.

Runtime policy can no longer redefine immutable platform capabilities.

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>
This commit is contained in:
Yang Wang
2026-07-30 09:50:40 +08:00
committed by Alex Deucher
parent d95700604f
commit 25f4a46b0c
4 changed files with 53 additions and 40 deletions

View File

@@ -1266,24 +1266,25 @@ static int arcturus_get_power_limit(struct smu_context *smu,
uint32_t *min_power_limit)
{
PPTable_t *pptable = smu->smu_table.driver_pptable;
uint32_t power_limit;
uint32_t current_limit, default_limit;
if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
/* the last hope to figure out the ppt limit */
if (!pptable) {
dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
return -EINVAL;
}
power_limit =
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
if (!pptable) {
dev_err(smu->adev->dev,
"Cannot get PPT limit due to pptable missing!");
return -EINVAL;
}
default_limit = pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
if (smu_v11_0_get_current_power_limit(smu, &current_limit))
current_limit = default_limit;
if (current_power_limit)
*current_power_limit = power_limit;
*current_power_limit = current_limit;
if (default_power_limit)
*default_power_limit = power_limit;
*default_power_limit = default_limit;
if (max_power_limit)
*max_power_limit = power_limit;
*max_power_limit = default_limit;
/*
* No lower bound is imposed on the limit. Any unreasonable limit set
* will result in frequent throttling.

View File

@@ -2144,22 +2144,26 @@ static int navi10_get_power_limit(struct smu_context *smu,
(struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
PPTable_t *pptable = smu->smu_table.driver_pptable;
uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
uint32_t current_limit, default_limit;
uint32_t od_percent_upper = 0, od_percent_lower = 0;
if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
/* the last hope to figure out the ppt limit */
if (!pptable) {
dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
return -EINVAL;
}
power_limit =
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
if (!pptable) {
dev_err(smu->adev->dev,
"Cannot get PPT limit due to pptable missing!");
return -EINVAL;
}
default_limit = smu->adev->pm.ac_power ?
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
pptable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
if (smu_v11_0_get_current_power_limit(smu, &current_limit))
current_limit = default_limit;
if (current_power_limit)
*current_power_limit = power_limit;
*current_power_limit = current_limit;
if (default_power_limit)
*default_power_limit = power_limit;
*default_power_limit = default_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@@ -2173,15 +2177,15 @@ static int navi10_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, default_limit);
if (max_power_limit) {
*max_power_limit = power_limit * (100 + od_percent_upper);
*max_power_limit = default_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 = default_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}

View File

@@ -633,20 +633,24 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
struct smu_11_0_7_powerplay_table *powerplay_table =
(struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
struct smu_11_0_7_overdrive_table *od_settings = smu->od_settings;
uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
uint16_t *table_member;
uint32_t current_limit, default_limit;
uint32_t od_percent_upper = 0, od_percent_lower = 0;
u16 *power_limit_ac, *power_limit_dc;
GET_PPTABLE_MEMBER(SocketPowerLimitAc, &table_member);
GET_PPTABLE_MEMBER(SocketPowerLimitAc, &power_limit_ac);
GET_PPTABLE_MEMBER(SocketPowerLimitDc, &power_limit_dc);
if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
power_limit =
table_member[PPT_THROTTLER_PPT0];
}
default_limit = smu->adev->pm.ac_power ?
power_limit_ac[PPT_THROTTLER_PPT0] :
power_limit_dc[PPT_THROTTLER_PPT0];
if (smu_v11_0_get_current_power_limit(smu, &current_limit))
current_limit = default_limit;
if (current_power_limit)
*current_power_limit = power_limit;
*current_power_limit = current_limit;
if (default_power_limit)
*default_power_limit = power_limit;
*default_power_limit = default_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@@ -660,15 +664,15 @@ static int sienna_cichlid_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, default_limit);
if (max_power_limit) {
*max_power_limit = power_limit * (100 + od_percent_upper);
*max_power_limit = default_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 = default_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
return 0;

View File

@@ -1156,8 +1156,12 @@ static int aldebaran_get_power_limit(struct smu_context *smu,
if (current_power_limit)
*current_power_limit = power_limit;
if (default_power_limit)
*default_power_limit = power_limit;
if (default_power_limit) {
if (pptable)
*default_power_limit = pptable->PptLimit;
else
*default_power_limit = power_limit;
}
if (max_power_limit) {
if (pptable)