* FAILED: patch "[PATCH] drm/amd/pm: preserve committed OD features for SMU 13.0.0/13.0.7" failed to apply to 5.10-stable tree
@ 2026-11-07 11:29 Sasha Levin
0 siblings, 0 replies; only message in thread
From: Sasha Levin @ 2026-11-07 11:29 UTC (permalink / raw)
To: kevin.wang, kenneth.feng, alosarjos, alexander.deucher; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 6027db7db773714f2e05df82093276f2a52a1fba
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107062956-failed-5.10-6027db7db773@kernel.org' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 6027db7db773714f2e05df82093276f2a52a1fba Mon Sep 17 00:00:00 2001
From: Kevin Wang <kevin.wang@amd.com>
Date: Thu, 15 Oct 2026 14:02:09 +0800
Subject: [PATCH] drm/amd/pm: preserve committed OD features for SMU
13.0.0/13.0.7
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
PMFW treats FeatureCtrlMask as the complete set of active OD features.
Uploads containing only newly edited bits can drop earlier settings.
Fix the OD state handling to:
- preserve committed features across later commits
- keep staged OD settings out of power-cap writes
- update cached state only after successful uploads
- clear restored features only after they return to defaults
- restore PPT for the current AC/DC source after resume
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/3625
Signed-off-by: Kevin Wang <kevin.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Tested-by: José Miguel Sarasola <alosarjos@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit adf63026e1fa706de48d986ac6c1a7cb64cbf927)
Cc: stable@vger.kernel.org
---
.../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 193 +++++++++++++-----
.../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 193 +++++++++++++-----
2 files changed, 293 insertions(+), 93 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 468aaeb79ffba..e80087e35e199 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
@@ -63,6 +63,9 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
int od_feature_bit,
int32_t *min, int32_t *max);
static int smu_v13_0_0_init_ppt_limits(struct smu_context *smu);
+static int
+smu_v13_0_0_upload_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table);
static const struct smu_feature_bits smu_v13_0_0_dpm_features = {
.bits = {
@@ -1079,6 +1082,93 @@ static bool smu_v13_0_0_is_od_feature_supported(struct smu_context *smu,
return feature_enabled;
}
+static u32
+smu_v13_0_0_filter_od_feature_mask(struct smu_context *smu, u32 feature_mask)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ u32 supported_mask =
+ pptable->SkuTable.OverDriveLimitsBasicMax.FeatureCtrlMask;
+
+ return feature_mask & supported_mask;
+}
+
+static bool smu_v13_0_0_fan_is_default(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot)
+{
+ return !memcmp(od->FanLinearPwmPoints, boot->FanLinearPwmPoints,
+ sizeof(od->FanLinearPwmPoints)) &&
+ !memcmp(od->FanLinearTempPoints, boot->FanLinearTempPoints,
+ sizeof(od->FanLinearTempPoints)) &&
+ od->FanMinimumPwm == boot->FanMinimumPwm &&
+ od->AcousticTargetRpmThreshold == boot->AcousticTargetRpmThreshold &&
+ od->AcousticLimitRpmThreshold == boot->AcousticLimitRpmThreshold &&
+ od->FanTargetTemperature == boot->FanTargetTemperature &&
+ od->FanMode == boot->FanMode;
+}
+
+static bool smu_v13_0_0_zero_fan_is_default(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot)
+{
+ return od->FanZeroRpmEnable == boot->FanZeroRpmEnable &&
+ od->FanZeroRpmStopTemp == boot->FanZeroRpmStopTemp;
+}
+
+static u32 smu_v13_0_0_normalize_feature_mask(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot,
+ u32 feature_mask)
+{
+ if (od->GfxclkFmin == boot->GfxclkFmin &&
+ od->GfxclkFmax == boot->GfxclkFmax)
+ feature_mask &= ~BIT(PP_OD_FEATURE_GFXCLK_BIT);
+ if (od->UclkFmin == boot->UclkFmin &&
+ od->UclkFmax == boot->UclkFmax)
+ feature_mask &= ~BIT(PP_OD_FEATURE_UCLK_BIT);
+ if (!memcmp(od->VoltageOffsetPerZoneBoundary,
+ boot->VoltageOffsetPerZoneBoundary,
+ sizeof(od->VoltageOffsetPerZoneBoundary)))
+ feature_mask &= ~BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT);
+ if (smu_v13_0_0_fan_is_default(od, boot))
+ feature_mask &= ~BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+ if (smu_v13_0_0_zero_fan_is_default(od, boot))
+ feature_mask &= ~BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ if (!od->Ppt)
+ feature_mask &= ~BIT(PP_OD_FEATURE_PPT_BIT);
+
+ return feature_mask;
+}
+
+static int
+smu_v13_0_0_upload_ppt_overdrive_table(struct smu_context *smu, s16 ppt)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table = table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ u32 next_mask = table_context->user_od_feature_mask;
+ int ret;
+
+ /* Do not commit OD settings staged after the last c operation. */
+ memcpy(&upload_table, user_od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.Ppt = ppt;
+ if (ppt)
+ next_mask |= BIT(PP_OD_FEATURE_PPT_BIT);
+ else
+ next_mask &= ~BIT(PP_OD_FEATURE_PPT_BIT);
+ upload_table.OverDriveTable.FeatureCtrlMask =
+ smu_v13_0_0_filter_od_feature_mask(smu, next_mask);
+
+ ret = smu_v13_0_0_upload_overdrive_table(smu, &upload_table);
+ if (ret)
+ return ret;
+
+ table_context->user_od_feature_mask =
+ upload_table.OverDriveTable.FeatureCtrlMask;
+ od_table->OverDriveTable.Ppt = ppt;
+ user_od_table->OverDriveTable.Ppt = ppt;
+
+ return 0;
+}
+
static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
int od_feature_bit,
int32_t *min,
@@ -1514,41 +1604,30 @@ static int smu_v13_0_0_od_restore_table_single(struct smu_context *smu, long inp
boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
}
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_ACOUSTIC_LIMIT:
od_table->OverDriveTable.AcousticLimitRpmThreshold =
boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_ACOUSTIC_TARGET:
od_table->OverDriveTable.AcousticTargetRpmThreshold =
boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
od_table->OverDriveTable.FanTargetTemperature =
boot_overdrive_table->OverDriveTable.FanTargetTemperature;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_MINIMUM_PWM:
od_table->OverDriveTable.FanMinimumPwm =
boot_overdrive_table->OverDriveTable.FanMinimumPwm;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
od_table->OverDriveTable.FanZeroRpmEnable =
boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
break;
case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
od_table->OverDriveTable.FanZeroRpmStopTemp =
boot_overdrive_table->OverDriveTable.FanZeroRpmStopTemp;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
break;
default:
dev_info(adev->dev, "Invalid table index: %ld\n", input);
@@ -1566,9 +1645,17 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu,
struct smu_table_context *table_context = &smu->smu_table;
OverDriveTableExternal_t *od_table =
(OverDriveTableExternal_t *)table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table =
+ (OverDriveTableExternal_t *)table_context->user_overdrive_table;
+ OverDriveTableExternal_t *boot_od_table =
+ (OverDriveTableExternal_t *)table_context->boot_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ OverDriveTable_t *od = &od_table->OverDriveTable;
+ OverDriveTable_t *boot = &boot_od_table->OverDriveTable;
struct amdgpu_device *adev = smu->adev;
uint32_t offset_of_voltageoffset;
int32_t minimum, maximum;
+ u32 next_mask;
int i, ret = 0;
switch (type) {
@@ -1892,36 +1979,41 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu,
} else {
memcpy(od_table,
table_context->boot_overdrive_table,
- sizeof(OverDriveTableExternal_t));
+ sizeof(OverDriveTableExternal_t));
od_table->OverDriveTable.FeatureCtrlMask = 0;
- table_context->user_od_feature_mask = 0;
}
fallthrough;
case PP_OD_COMMIT_DPM_TABLE:
- table_context->user_od_feature_mask =
- od_table->OverDriveTable.FeatureCtrlMask;
offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
- if (memcmp((u8 *)od_table + offset_of_voltageoffset,
- table_context->user_overdrive_table + offset_of_voltageoffset,
- sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
- smu_v13_0_0_dump_od_table(smu, od_table);
+ next_mask = smu_v13_0_0_filter_od_feature_mask(smu,
+ table_context->user_od_feature_mask |
+ od->FeatureCtrlMask);
+ next_mask = smu_v13_0_0_normalize_feature_mask(od, boot,
+ next_mask);
- ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
+ if (memcmp((u8 *)od_table + offset_of_voltageoffset,
+ (u8 *)user_od_table + offset_of_voltageoffset,
+ sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset) ||
+ next_mask != table_context->user_od_feature_mask) {
+ memcpy(&upload_table, od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.FeatureCtrlMask = next_mask;
+ smu_v13_0_0_dump_od_table(smu, &upload_table);
+
+ ret = smu_v13_0_0_upload_overdrive_table(smu, &upload_table);
if (ret) {
dev_err(adev->dev, "Failed to upload overdrive table!\n");
return ret;
}
- memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
+ table_context->user_od_feature_mask = next_mask;
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ memcpy((u8 *)user_od_table + offset_of_voltageoffset,
(u8 *)od_table + offset_of_voltageoffset,
sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
- if (!memcmp(table_context->user_overdrive_table,
- table_context->boot_overdrive_table,
- sizeof(OverDriveTableExternal_t)))
- smu->user_dpm_profile.user_od = false;
- else
- smu->user_dpm_profile.user_od = true;
+ smu->user_dpm_profile.user_od =
+ !!(next_mask & ~BIT(PP_OD_FEATURE_PPT_BIT));
}
break;
@@ -2184,6 +2276,7 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
memcpy(od_table,
boot_od_table,
sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
/*
* For S3/S4/Runpm resume, we need to setup those overdrive tables again,
@@ -2193,6 +2286,7 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
memcpy(user_od_table,
boot_od_table,
sizeof(OverDriveTableExternal_t));
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
smu->user_dpm_profile.user_od = false;
smu->smu_table.user_od_feature_mask = 0;
} else if (smu->user_dpm_profile.user_od) {
@@ -2231,6 +2325,14 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
user_od_table->OverDriveTable.FanZeroRpmStopTemp =
user_od_table_bak.OverDriveTable.FanZeroRpmStopTemp;
+ user_od_table->OverDriveTable.FanMode =
+ user_od_table_bak.OverDriveTable.FanMode;
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
+ }
+ if (smu->adev->in_suspend) {
+ user_od_table->OverDriveTable.Ppt = 0;
+ smu->smu_table.user_od_feature_mask &=
+ ~BIT(PP_OD_FEATURE_PPT_BIT);
}
smu_v13_0_0_set_supported_od_feature_mask(smu);
@@ -2243,13 +2345,22 @@ static int smu_v13_0_0_restore_user_od_settings(struct smu_context *smu)
struct smu_table_context *table_context = &smu->smu_table;
OverDriveTableExternal_t *od_table = table_context->overdrive_table;
OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ u32 next_mask;
int res;
- user_od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
- res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table);
- user_od_table->OverDriveTable.FeatureCtrlMask = 0;
- if (res == 0)
+
+ next_mask = smu_v13_0_0_filter_od_feature_mask(smu,
+ table_context->user_od_feature_mask);
+ memcpy(&upload_table, user_od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.FeatureCtrlMask = next_mask;
+ res = smu_v13_0_0_upload_overdrive_table(smu, &upload_table);
+ if (res == 0) {
+ table_context->user_od_feature_mask = next_mask;
+ smu->user_dpm_profile.user_od =
+ !!(next_mask & ~BIT(PP_OD_FEATURE_PPT_BIT));
memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ }
return res;
}
@@ -3043,10 +3154,8 @@ static int smu_v13_0_0_set_ppt_limit(struct smu_context *smu,
SkuTable_t *skutable = &pptable->SkuTable;
uint32_t msg_limit = skutable->MsgLimits.Power
[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
- struct smu_table_context *table_context = &smu->smu_table;
- OverDriveTableExternal_t *od_table =
- (OverDriveTableExternal_t *)table_context->overdrive_table;
OverDriveTableExternal_t current_od_table;
+ s16 ppt;
int ret = 0;
if (limit_type != SMU_PPT_LIMIT_PPT0)
@@ -3058,12 +3167,7 @@ static int smu_v13_0_0_set_ppt_limit(struct smu_context *smu,
return ret;
if (current_od_table.OverDriveTable.Ppt) {
- od_table->OverDriveTable.Ppt = 0;
- table_context->user_od_feature_mask &=
- ~(1U << PP_OD_FEATURE_PPT_BIT);
- od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
- ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
+ ret = smu_v13_0_0_upload_ppt_overdrive_table(smu, 0);
if (ret) {
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
return ret;
@@ -3075,11 +3179,8 @@ static int smu_v13_0_0_set_ppt_limit(struct smu_context *smu,
if (ret)
return ret;
- od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
- table_context->user_od_feature_mask |= 1U << PP_OD_FEATURE_PPT_BIT;
- od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
- ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
+ ppt = (limit * 100) / msg_limit - 100;
+ ret = smu_v13_0_0_upload_ppt_overdrive_table(smu, ppt);
if (ret) {
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
return ret;
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 51e419e6380c1..8285d4a91589a 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
@@ -63,6 +63,9 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
int od_feature_bit,
int32_t *min, int32_t *max);
static int smu_v13_0_7_init_ppt_limits(struct smu_context *smu);
+static int
+smu_v13_0_7_upload_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table);
static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
.bits = {
@@ -94,6 +97,7 @@ static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
#define PP_OD_FEATURE_GFXCLK_FMAX 1
#define PP_OD_FEATURE_UCLK_FMIN 2
#define PP_OD_FEATURE_UCLK_FMAX 3
+
#define PP_OD_FEATURE_GFX_VF_CURVE 4
#define PP_OD_FEATURE_FAN_CURVE_TEMP 5
#define PP_OD_FEATURE_FAN_CURVE_PWM 6
@@ -1089,6 +1093,93 @@ static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
return feature_enabled;
}
+static u32
+smu_v13_0_7_filter_od_feature_mask(struct smu_context *smu, u32 feature_mask)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ u32 supported_mask =
+ pptable->SkuTable.OverDriveLimitsBasicMax.FeatureCtrlMask;
+
+ return feature_mask & supported_mask;
+}
+
+static bool smu_v13_0_7_fan_is_default(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot)
+{
+ return !memcmp(od->FanLinearPwmPoints, boot->FanLinearPwmPoints,
+ sizeof(od->FanLinearPwmPoints)) &&
+ !memcmp(od->FanLinearTempPoints, boot->FanLinearTempPoints,
+ sizeof(od->FanLinearTempPoints)) &&
+ od->FanMinimumPwm == boot->FanMinimumPwm &&
+ od->AcousticTargetRpmThreshold == boot->AcousticTargetRpmThreshold &&
+ od->AcousticLimitRpmThreshold == boot->AcousticLimitRpmThreshold &&
+ od->FanTargetTemperature == boot->FanTargetTemperature &&
+ od->FanMode == boot->FanMode;
+}
+
+static bool smu_v13_0_7_zero_fan_is_default(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot)
+{
+ return od->FanZeroRpmEnable == boot->FanZeroRpmEnable &&
+ od->FanZeroRpmStopTemp == boot->FanZeroRpmStopTemp;
+}
+
+static u32 smu_v13_0_7_normalize_feature_mask(const OverDriveTable_t *od,
+ const OverDriveTable_t *boot,
+ u32 feature_mask)
+{
+ if (od->GfxclkFmin == boot->GfxclkFmin &&
+ od->GfxclkFmax == boot->GfxclkFmax)
+ feature_mask &= ~BIT(PP_OD_FEATURE_GFXCLK_BIT);
+ if (od->UclkFmin == boot->UclkFmin &&
+ od->UclkFmax == boot->UclkFmax)
+ feature_mask &= ~BIT(PP_OD_FEATURE_UCLK_BIT);
+ if (!memcmp(od->VoltageOffsetPerZoneBoundary,
+ boot->VoltageOffsetPerZoneBoundary,
+ sizeof(od->VoltageOffsetPerZoneBoundary)))
+ feature_mask &= ~BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT);
+ if (smu_v13_0_7_fan_is_default(od, boot))
+ feature_mask &= ~BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
+ if (smu_v13_0_7_zero_fan_is_default(od, boot))
+ feature_mask &= ~BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ if (!od->Ppt)
+ feature_mask &= ~BIT(PP_OD_FEATURE_PPT_BIT);
+
+ return feature_mask;
+}
+
+static int
+smu_v13_0_7_upload_ppt_overdrive_table(struct smu_context *smu, s16 ppt)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table = table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ u32 next_mask = table_context->user_od_feature_mask;
+ int ret;
+
+ /* Do not commit OD settings staged after the last c operation. */
+ memcpy(&upload_table, user_od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.Ppt = ppt;
+ if (ppt)
+ next_mask |= BIT(PP_OD_FEATURE_PPT_BIT);
+ else
+ next_mask &= ~BIT(PP_OD_FEATURE_PPT_BIT);
+ upload_table.OverDriveTable.FeatureCtrlMask =
+ smu_v13_0_7_filter_od_feature_mask(smu, next_mask);
+
+ ret = smu_v13_0_7_upload_overdrive_table(smu, &upload_table);
+ if (ret)
+ return ret;
+
+ table_context->user_od_feature_mask =
+ upload_table.OverDriveTable.FeatureCtrlMask;
+ od_table->OverDriveTable.Ppt = ppt;
+ user_od_table->OverDriveTable.Ppt = ppt;
+
+ return 0;
+}
+
static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
int od_feature_bit,
int32_t *min,
@@ -1523,41 +1614,30 @@ static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long inp
boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
}
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_ACOUSTIC_LIMIT:
od_table->OverDriveTable.AcousticLimitRpmThreshold =
boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_ACOUSTIC_TARGET:
od_table->OverDriveTable.AcousticTargetRpmThreshold =
boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
od_table->OverDriveTable.FanTargetTemperature =
boot_overdrive_table->OverDriveTable.FanTargetTemperature;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_MINIMUM_PWM:
od_table->OverDriveTable.FanMinimumPwm =
boot_overdrive_table->OverDriveTable.FanMinimumPwm;
- od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
od_table->OverDriveTable.FanZeroRpmEnable =
boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
break;
case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
od_table->OverDriveTable.FanZeroRpmStopTemp =
boot_overdrive_table->OverDriveTable.FanZeroRpmStopTemp;
- od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
break;
default:
dev_info(adev->dev, "Invalid table index: %ld\n", input);
@@ -1575,9 +1655,17 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
struct smu_table_context *table_context = &smu->smu_table;
OverDriveTableExternal_t *od_table =
(OverDriveTableExternal_t *)table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table =
+ (OverDriveTableExternal_t *)table_context->user_overdrive_table;
+ OverDriveTableExternal_t *boot_od_table =
+ (OverDriveTableExternal_t *)table_context->boot_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ OverDriveTable_t *od = &od_table->OverDriveTable;
+ OverDriveTable_t *boot = &boot_od_table->OverDriveTable;
struct amdgpu_device *adev = smu->adev;
uint32_t offset_of_voltageoffset;
int32_t minimum, maximum;
+ u32 next_mask;
int i, ret = 0;
switch (type) {
@@ -1903,35 +1991,40 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
table_context->boot_overdrive_table,
sizeof(OverDriveTableExternal_t));
od_table->OverDriveTable.FeatureCtrlMask = 0;
- table_context->user_od_feature_mask = 0;
}
fallthrough;
case PP_OD_COMMIT_DPM_TABLE:
- table_context->user_od_feature_mask =
- od_table->OverDriveTable.FeatureCtrlMask;
offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
- if (memcmp((u8 *)od_table + offset_of_voltageoffset,
- table_context->user_overdrive_table + offset_of_voltageoffset,
- sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
- smu_v13_0_7_dump_od_table(smu, od_table);
+ next_mask = smu_v13_0_7_filter_od_feature_mask(smu,
+ table_context->user_od_feature_mask |
+ od->FeatureCtrlMask);
+ next_mask = smu_v13_0_7_normalize_feature_mask(od, boot,
+ next_mask);
- ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
+ if (memcmp((u8 *)od_table + offset_of_voltageoffset,
+ (u8 *)user_od_table + offset_of_voltageoffset,
+ sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset) ||
+ next_mask != table_context->user_od_feature_mask) {
+ memcpy(&upload_table, od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.FeatureCtrlMask = next_mask;
+ smu_v13_0_7_dump_od_table(smu, &upload_table);
+
+ ret = smu_v13_0_7_upload_overdrive_table(smu, &upload_table);
if (ret) {
dev_err(adev->dev, "Failed to upload overdrive table!\n");
return ret;
}
- memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
+ table_context->user_od_feature_mask = next_mask;
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ memcpy((u8 *)user_od_table + offset_of_voltageoffset,
(u8 *)od_table + offset_of_voltageoffset,
sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
- if (!memcmp(table_context->user_overdrive_table,
- table_context->boot_overdrive_table,
- sizeof(OverDriveTableExternal_t)))
- smu->user_dpm_profile.user_od = false;
- else
- smu->user_dpm_profile.user_od = true;
+ smu->user_dpm_profile.user_od =
+ !!(next_mask & ~BIT(PP_OD_FEATURE_PPT_BIT));
}
break;
@@ -2186,6 +2279,7 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
memcpy(od_table,
boot_od_table,
sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
/*
* For S3/S4/Runpm resume, we need to setup those overdrive tables again,
@@ -2195,6 +2289,7 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
memcpy(user_od_table,
boot_od_table,
sizeof(OverDriveTableExternal_t));
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
smu->user_dpm_profile.user_od = false;
smu->smu_table.user_od_feature_mask = 0;
} else if (smu->user_dpm_profile.user_od) {
@@ -2233,6 +2328,14 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
user_od_table->OverDriveTable.FanZeroRpmStopTemp =
user_od_table_bak.OverDriveTable.FanZeroRpmStopTemp;
+ user_od_table->OverDriveTable.FanMode =
+ user_od_table_bak.OverDriveTable.FanMode;
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
+ }
+ if (smu->adev->in_suspend) {
+ user_od_table->OverDriveTable.Ppt = 0;
+ smu->smu_table.user_od_feature_mask &=
+ ~BIT(PP_OD_FEATURE_PPT_BIT);
}
smu_v13_0_7_set_supported_od_feature_mask(smu);
@@ -2245,14 +2348,22 @@ static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu)
struct smu_table_context *table_context = &smu->smu_table;
OverDriveTableExternal_t *od_table = table_context->overdrive_table;
OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ OverDriveTableExternal_t upload_table;
+ u32 next_mask;
int res;
- user_od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
- res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table);
- user_od_table->OverDriveTable.FeatureCtrlMask = 0;
- if (res == 0)
+ next_mask = smu_v13_0_7_filter_od_feature_mask(smu,
+ table_context->user_od_feature_mask);
+ memcpy(&upload_table, user_od_table, sizeof(upload_table));
+ upload_table.OverDriveTable.FeatureCtrlMask = next_mask;
+ res = smu_v13_0_7_upload_overdrive_table(smu, &upload_table);
+ if (res == 0) {
+ table_context->user_od_feature_mask = next_mask;
+ smu->user_dpm_profile.user_od =
+ !!(next_mask & ~BIT(PP_OD_FEATURE_PPT_BIT));
memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ }
return res;
}
@@ -2664,10 +2775,8 @@ static int smu_v13_0_7_set_ppt_limit(struct smu_context *smu,
SkuTable_t *skutable = &pptable->SkuTable;
uint32_t msg_limit = skutable->MsgLimits.Power
[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
- struct smu_table_context *table_context = &smu->smu_table;
- OverDriveTableExternal_t *od_table =
- (OverDriveTableExternal_t *)table_context->overdrive_table;
OverDriveTableExternal_t current_od_table;
+ s16 ppt;
int ret = 0;
if (limit_type != SMU_PPT_LIMIT_PPT0)
@@ -2679,13 +2788,7 @@ static int smu_v13_0_7_set_ppt_limit(struct smu_context *smu,
return ret;
if (current_od_table.OverDriveTable.Ppt) {
- od_table->OverDriveTable.Ppt = 0;
- table_context->user_od_feature_mask &=
- ~(1U << PP_OD_FEATURE_PPT_BIT);
- od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
-
- ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
+ ret = smu_v13_0_7_upload_ppt_overdrive_table(smu, 0);
if (ret) {
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
return ret;
@@ -2697,12 +2800,8 @@ static int smu_v13_0_7_set_ppt_limit(struct smu_context *smu,
if (ret)
return ret;
- od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
- table_context->user_od_feature_mask |= 1U << PP_OD_FEATURE_PPT_BIT;
- od_table->OverDriveTable.FeatureCtrlMask =
- table_context->user_od_feature_mask;
-
- ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
+ ppt = (limit * 100) / msg_limit - 100;
+ ret = smu_v13_0_7_upload_ppt_overdrive_table(smu, ppt);
if (ret) {
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-07 11:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 11:29 FAILED: patch "[PATCH] drm/amd/pm: preserve committed OD features for SMU 13.0.0/13.0.7" failed to apply to 5.10-stable tree Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox