From 25f4a46b0c8acd77c9065b50a1fe48af27d91fdf Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Thu, 30 Jul 2026 09:50:40 +0800 Subject: [PATCH] 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 Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 25 ++++++++------- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 32 +++++++++++-------- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 28 +++++++++------- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 8 +++-- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index e7628f4f1de4..978f86ac12fb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -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, ¤t_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. diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 9f8ab4e097dd..a47d49dd3ff0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -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, ¤t_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; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index cef6287524d4..b90878c2c8ef 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -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, ¤t_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; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index cbdfde79cb9e..5dee4cdbb971 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -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)