* [PATCH 1/9] drm/amd/pm/ci: Use highest MCLK on CI when MCLK DPM is disabled
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
@ 2026-03-29 16:02 ` Timur Kristóf
2026-03-29 16:02 ` [PATCH 2/9] drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs Timur Kristóf
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:02 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
When MCLK DPM is disabled for any reason, populate the MCLK
table with the highest MCLK DPM level, so that the ASIC can
use the highest possible memory clock to get good performance
even when MCLK DPM is disabled.
Fixes: 9f4b35411cfe ("drm/amd/powerplay: add CI asics support to smumgr (v3)")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
index ad1fd3150d03e..858f118130452 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
@@ -1322,6 +1322,14 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
return result;
}
+ if (data->mclk_dpm_key_disabled && dpm_table->mclk_table.count) {
+ /* Populate the table with the highest MCLK level when MCLK DPM is disabled */
+ for (i = 0; i < dpm_table->mclk_table.count - 1; i++) {
+ levels[i] = levels[dpm_table->mclk_table.count - 1];
+ levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
+ }
+ }
+
smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
dev_id = adev->pdev->device;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 2/9] drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
2026-03-29 16:02 ` [PATCH 1/9] drm/amd/pm/ci: Use highest MCLK on CI when MCLK DPM is disabled Timur Kristóf
@ 2026-03-29 16:02 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 3/9] drm/amd/pm/smu7: Fix SMU7 voltage dependency on display clock Timur Kristóf
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:02 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
There are two known cases where MCLK DPM can causes issues:
Radeon R9 M380 found in iMac computers from 2015.
The SMU in this GPU just hangs as soon as we send it the
PPSMC_MSG_MCLKDPM_Enable command, even when MCLK switching is
disabled, and even when we only populate one MCLK DPM level.
Apply workaround to all devices with the same subsystem ID.
Radeon R7 260X due to old memory controller microcode.
We only flash the MC ucode when it isn't set up by the VBIOS,
therefore there is no way to make sure that it has the correct
ucode version.
I verified that this patch fixes the SMU hang on the R9 M380
which would previously fail to boot. This also fixes the UVD
initialization error on that GPU which happened because the
SMU couldn't ungate the UVD after it hung.
Fixes: 86457c3b21cb ("drm/amd/powerplay: Add support for CI asics to hwmgr")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
index 2b5ac21fee399..1d6e30269d567 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
@@ -104,6 +104,21 @@ int hwmgr_early_init(struct pp_hwmgr *hwmgr)
PP_GFXOFF_MASK);
hwmgr->pp_table_version = PP_TABLE_V0;
hwmgr->od_enabled = false;
+ switch (hwmgr->chip_id) {
+ case CHIP_BONAIRE:
+ /* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM
+ * R7 260X cards with old MC ucode: MCLK DPM is unstable
+ */
+ if (adev->pdev->subsystem_vendor == 0x106B ||
+ adev->pdev->device == 0x6658) {
+ dev_info(adev->dev, "disabling MCLK DPM on quirky ASIC");
+ adev->pm.pp_feature &= ~PP_MCLK_DPM_MASK;
+ hwmgr->feature_mask &= ~PP_MCLK_DPM_MASK;
+ }
+ break;
+ default:
+ break;
+ }
smu7_init_function_pointers(hwmgr);
break;
case AMDGPU_FAMILY_CZ:
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 3/9] drm/amd/pm/smu7: Fix SMU7 voltage dependency on display clock
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
2026-03-29 16:02 ` [PATCH 1/9] drm/amd/pm/ci: Use highest MCLK on CI when MCLK DPM is disabled Timur Kristóf
2026-03-29 16:02 ` [PATCH 2/9] drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 4/9] drm/amd/pm/smu7: Remove non-functional SMU7 voltage dependency on DAL Timur Kristóf
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
The DCE (display controller engine) requires a minimum voltage
in order to function correctly, depending on which clock level
it currently uses.
Add a new table that contains display clock frequency levels
and the corresponding required voltages. The clock frequency
levels are taken from DC (and the old radeon driver's voltage
dependency table for CI in cases where its values were lower).
The voltage levels are taken from the following function:
phm_initializa_dynamic_state_adjustment_rule_settings().
Furthermore, in case of CI, call smu7_patch_vddc() on the new
table to account for leakage voltage (like in radeon).
Use the display clock value from amd_pp_display_configuration
to look up the voltage level needed by the DCE. Send the
voltage to the SMU via the PPSMC_MSG_VddC_Request command.
The previous implementation of this feature was non-functional
because it relied on a "dal_power_level" field which was never
assigned; and it was not at all implemented for CI ASICs.
I verified this on a Radeon R9 M380 which previously booted to
a black screen with DC enabled (default since Linux 6.19), but
now works correctly.
Fixes: 599a7e9fe1b6 ("drm/amd/powerplay: implement smu7 hwmgr to manager asics with smu ip version 7.")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
.../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 88 ++++++++++++++++++-
drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 1 +
2 files changed, 86 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index 2be584aefd0ad..338d651bca4dd 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -2802,6 +2802,10 @@ static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
if (tmp)
return -EINVAL;
+ tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_display_clock);
+ if (tmp)
+ return -EINVAL;
+
tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table);
if (tmp)
return -EINVAL;
@@ -2885,6 +2889,8 @@ static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
{
kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+ kfree(hwmgr->dyn_state.vddc_dependency_on_display_clock);
+ hwmgr->dyn_state.vddc_dependency_on_display_clock = NULL;
kfree(hwmgr->backend);
hwmgr->backend = NULL;
@@ -2955,6 +2961,51 @@ static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
return ret;
}
+static int smu7_init_voltage_dependency_on_display_clock_table(struct pp_hwmgr *hwmgr)
+{
+ struct phm_clock_voltage_dependency_table *table;
+
+ if (!amdgpu_device_ip_get_ip_block(hwmgr->adev, AMD_IP_BLOCK_TYPE_DCE))
+ return 0;
+
+ table = kzalloc(struct_size(table, entries, 4), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ if (hwmgr->chip_id >= CHIP_POLARIS10) {
+ table->entries[0].clk = 38918;
+ table->entries[1].clk = 45900;
+ table->entries[2].clk = 66700;
+ table->entries[3].clk = 113200;
+
+ table->entries[0].v = 700;
+ table->entries[1].v = 740;
+ table->entries[2].v = 800;
+ table->entries[3].v = 900;
+ } else {
+ if (hwmgr->chip_family == AMDGPU_FAMILY_CZ) {
+ table->entries[0].clk = 35200;
+ table->entries[1].clk = 35200;
+ table->entries[2].clk = 46700;
+ table->entries[3].clk = 64300;
+ } else {
+ table->entries[0].clk = 0;
+ table->entries[1].clk = 35200;
+ table->entries[2].clk = 54000;
+ table->entries[3].clk = 62500;
+ }
+
+ table->entries[0].v = 0;
+ table->entries[1].v = 720;
+ table->entries[2].v = 810;
+ table->entries[3].v = 900;
+ }
+
+ table->count = 4;
+ hwmgr->dyn_state.vddc_dependency_on_display_clock = table;
+ return 0;
+}
+
static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
@@ -2983,6 +3034,10 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_get_elb_voltages(hwmgr);
}
+ result = smu7_init_voltage_dependency_on_display_clock_table(hwmgr);
+ if (result)
+ goto fail;
+
if (hwmgr->pp_table_version == PP_TABLE_V1) {
smu7_complete_dependency_tables(hwmgr);
smu7_set_private_data_based_on_pptable_v1(hwmgr);
@@ -3079,13 +3134,40 @@ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
return 0;
}
+static uint32_t smu7_lookup_vddc_from_dispclk(struct pp_hwmgr *hwmgr)
+{
+ const struct amd_pp_display_configuration *cfg = hwmgr->display_config;
+ const struct phm_clock_voltage_dependency_table *vddc_dep_on_dispclk =
+ hwmgr->dyn_state.vddc_dependency_on_display_clock;
+ uint32_t i;
+
+ if (!vddc_dep_on_dispclk || !vddc_dep_on_dispclk->count ||
+ !cfg || !cfg->num_display || !cfg->display_clk)
+ return 0;
+
+ /* Start from 1 because ClocksStateUltraLow should not be used according to DC. */
+ for (i = 1; i < vddc_dep_on_dispclk->count; ++i)
+ if (vddc_dep_on_dispclk->entries[i].clk >= cfg->display_clk)
+ return vddc_dep_on_dispclk->entries[i].v;
+
+ return vddc_dep_on_dispclk->entries[vddc_dep_on_dispclk->count - 1].v;
+}
+
+static void smu7_apply_minimum_dce_voltage_request(struct pp_hwmgr *hwmgr)
+{
+ uint32_t req_vddc = smu7_lookup_vddc_from_dispclk(hwmgr);
+
+ smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_VddC_Request,
+ req_vddc * VOLTAGE_SCALE,
+ NULL);
+}
+
static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
- if (hwmgr->pp_table_version == PP_TABLE_V1)
- phm_apply_dal_min_voltage_request(hwmgr);
-/* TO DO for v0 iceland and Ci*/
+ smu7_apply_minimum_dce_voltage_request(hwmgr);
if (!data->sclk_dpm_key_disabled) {
if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index c661185753b42..2f49c95342a14 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
@@ -631,6 +631,7 @@ struct phm_dynamic_state_info {
struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk;
struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk;
struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk;
+ struct phm_clock_voltage_dependency_table *vddc_dependency_on_display_clock;
struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl;
struct phm_clock_array *valid_sclk_values;
struct phm_clock_array *valid_mclk_values;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 4/9] drm/amd/pm/smu7: Remove non-functional SMU7 voltage dependency on DAL
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (2 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 3/9] drm/amd/pm/smu7: Fix SMU7 voltage dependency on display clock Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 5/9] drm/amd/pm/ci: Fix powertune defaults for Hawaii 0x67B0 Timur Kristóf
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
It looks like this was written for an old version of DC (DAL)
and was never adapted afterwards. This was non-functional
because it relied on the "dal_power_level" field which was
never assigned anywhere in the code base.
Also, it was not implemented for CI ASICs.
Now superseded by the newer voltage dependency on display
clock table added by the previous commit, let's remove.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
.../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 9 --
.../drm/amd/pm/powerplay/hwmgr/smu_helper.c | 84 -------------------
.../drm/amd/pm/powerplay/hwmgr/smu_helper.h | 2 -
drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 1 -
4 files changed, 96 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index 338d651bca4dd..c357b1f638cfb 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -2794,10 +2794,6 @@ static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
if (tmp)
return -EINVAL;
- tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
- if (tmp)
- return -EINVAL;
-
tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
if (tmp)
return -EINVAL;
@@ -2887,8 +2883,6 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
{
- kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
kfree(hwmgr->dyn_state.vddc_dependency_on_display_clock);
hwmgr->dyn_state.vddc_dependency_on_display_clock = NULL;
kfree(hwmgr->backend);
@@ -3046,9 +3040,6 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_set_private_data_based_on_pptable_v0(hwmgr);
}
- /* Initalize Dynamic State Adjustment Rule Settings */
- result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
-
if (result)
goto fail;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
index c305ea4ec17d2..5d454b18905ce 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
@@ -485,53 +485,6 @@ int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
return 0;
}
-/**
- * phm_initializa_dynamic_state_adjustment_rule_settings - Initialize Dynamic State Adjustment Rule Settings
- *
- * @hwmgr: the address of the powerplay hardware manager.
- */
-int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
-{
- struct phm_clock_voltage_dependency_table *table_clk_vlt;
- struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
-
- /* initialize vddc_dep_on_dal_pwrl table */
- table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 4),
- GFP_KERNEL);
-
- if (NULL == table_clk_vlt) {
- pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n");
- return -ENOMEM;
- } else {
- table_clk_vlt->count = 4;
- table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[0].v = 700;
- else
- table_clk_vlt->entries[0].v = 0;
- table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[1].v = 740;
- else
- table_clk_vlt->entries[1].v = 720;
- table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
- if (hwmgr->chip_id >= CHIP_POLARIS10 &&
- hwmgr->chip_id <= CHIP_VEGAM)
- table_clk_vlt->entries[2].v = 800;
- else
- table_clk_vlt->entries[2].v = 810;
- table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
- table_clk_vlt->entries[3].v = 900;
- if (pptable_info != NULL)
- pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
- }
-
- return 0;
-}
-
uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
{
uint32_t level = 0;
@@ -542,43 +495,6 @@ uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
return level;
}
-void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
-{
- struct phm_ppt_v1_information *table_info =
- (struct phm_ppt_v1_information *)hwmgr->pptable;
- struct phm_clock_voltage_dependency_table *table =
- table_info->vddc_dep_on_dal_pwrl;
- struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
- enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
- uint32_t req_vddc = 0, req_volt, i;
-
- if (!table || table->count <= 0
- || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
- || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
- return;
-
- for (i = 0; i < table->count; i++) {
- if (dal_power_level == table->entries[i].clk) {
- req_vddc = table->entries[i].v;
- break;
- }
- }
-
- vddc_table = table_info->vdd_dep_on_sclk;
- for (i = 0; i < vddc_table->count; i++) {
- if (req_vddc <= vddc_table->entries[i].vddc) {
- req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
- smum_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_VddC_Request,
- req_volt,
- NULL);
- return;
- }
- }
- pr_err("DAL requested level can not"
- " found a available voltage in VDDC DPM Table \n");
-}
-
int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage)
{
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
index 83b3c9315143e..d370bfd0764d8 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h
@@ -87,9 +87,7 @@ extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_t
extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level);
extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table,
uint16_t virtual_voltage_id, int32_t *sclk);
-extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
-extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index 2f49c95342a14..3ae45eac0c5ca 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
@@ -773,7 +773,6 @@ struct pp_hwmgr {
const struct pp_smumgr_func *smumgr_funcs;
bool is_kicker;
- enum PP_DAL_POWERLEVEL dal_power_level;
struct phm_dynamic_state_info dyn_state;
const struct pp_hwmgr_func *hwmgr_func;
const struct pp_table_func *pptable_func;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/9] drm/amd/pm/ci: Fix powertune defaults for Hawaii 0x67B0
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (3 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 4/9] drm/amd/pm/smu7: Remove non-functional SMU7 voltage dependency on DAL Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 6/9] drm/amd/pm/ci: Clear EnabledForActivity field for memory levels Timur Kristóf
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
There is no AMD GPU with the ID 0x66B0, this looks like a typo.
It should be 0x67B0 which is actually part of the PCI ID list,
and should use the Hawaii XT powertune defaults according to
the old radeon driver.
Fixes: 9f4b35411cfe ("drm/amd/powerplay: add CI asics support to smumgr (v3)")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
index 858f118130452..6382dee5a2ba3 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
@@ -245,7 +245,7 @@ static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
smu_data->power_tune_defaults = &defaults_hawaii_pro;
break;
case 0x67B8:
- case 0x66B0:
+ case 0x67B0:
smu_data->power_tune_defaults = &defaults_hawaii_xt;
break;
case 0x6640:
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 6/9] drm/amd/pm/ci: Clear EnabledForActivity field for memory levels
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (4 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 5/9] drm/amd/pm/ci: Fix powertune defaults for Hawaii 0x67B0 Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 7/9] drm/amd/pm/ci: Fill DW8 fields from SMC Timur Kristóf
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
Follow what radeon did and what amdgpu does for other GPUs with SMU7.
Fixes: 9f4b35411cfe ("drm/amd/powerplay: add CI asics support to smumgr (v3)")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
index 6382dee5a2ba3..90cb75ae02ff4 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
@@ -1217,7 +1217,7 @@ static int ci_populate_single_memory_level(
}
memory_level->EnabledForThrottle = 1;
- memory_level->EnabledForActivity = 1;
+ memory_level->EnabledForActivity = 0;
memory_level->UpH = data->current_profile_setting.mclk_up_hyst;
memory_level->DownH = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownH = 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 7/9] drm/amd/pm/ci: Fill DW8 fields from SMC
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (5 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 6/9] drm/amd/pm/ci: Clear EnabledForActivity field for memory levels Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 8/9] drm/amd/pm/smu7: Add SCLK cap for quirky Hawaii board Timur Kristóf
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
In ci_populate_dw8() we currently just read a value from the SMU
and then throw it away. Instead of throwing away the value,
we should use it to fill other fields in DW8 (like radeon).
Otherwise the value of the other fiels is just cleared when
we copy this data to the SMU later.
Fixes: 9f4b35411cfe ("drm/amd/powerplay: add CI asics support to smumgr (v3)")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
index 90cb75ae02ff4..69d8b05ef2457 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
@@ -543,12 +543,11 @@ static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
{
struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
- uint32_t temp;
if (ci_read_smc_sram_dword(hwmgr,
fuse_table_offset +
offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl),
- (uint32_t *)&temp, SMC_RAM_END))
+ (uint32_t *)&smu_data->power_tune_table.TdcWaterfallCtl, SMC_RAM_END))
PP_ASSERT_WITH_CODE(false,
"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
return -EINVAL);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 8/9] drm/amd/pm/smu7: Add SCLK cap for quirky Hawaii board
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (6 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 7/9] drm/amd/pm/ci: Fill DW8 fields from SMC Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-29 16:03 ` [PATCH 9/9] drm/amdgpu/uvd4.2: Don't initialize UVD 4.2 when DPM is disabled Timur Kristóf
2026-03-30 15:52 ` [PATCH 0/9] Various SMU7 power management fixes Alex Deucher
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
On a specific Radeon R9 390X board, the GPU can "randomly" hang
while gaming. Initially I thought this was a RADV bug and tried
to work around this in Mesa:
commit 8ea08747b86b ("radv: Mitigate GPU hang on Hawaii in Dota 2 and RotTR")
However, I got some feedback from other users who are reporting
that the above mitigation causes a significant performance
regression for them, and they didn't experience the hang on their
GPU in the first place.
After some further investigation, it turns out that the problem
is that the highest SCLK DPM level on this board isn't stable.
Lowering SCLK to 1040 MHz (from 1070 MHz) works around the issue,
and has a negligible impact on performance compared to the Mesa
patch. (Note that increasing the voltage can also work around it,
but we felt that lowering the SCLK is the safer option.)
To solve the above issue, add an "sclk_cap" field to smu7_hwmgr
and set this field for the affected board. The capped SCLK value
correctly appears on the sysfs interface and shows up in GUI
tools such as LACT.
Fixes: 9f4b35411cfe ("drm/amd/powerplay: add CI asics support to smumgr (v3)")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
.../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 30 ++++++++++++++++---
.../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h | 1 +
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index c357b1f638cfb..1381902547b8e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -787,7 +787,7 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
hwmgr->dyn_state.vddc_dependency_on_mclk;
struct phm_cac_leakage_table *std_voltage_table =
hwmgr->dyn_state.cac_leakage_table;
- uint32_t i;
+ uint32_t i, clk;
PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
"SCLK dependency table is missing. This table is mandatory", return -EINVAL);
@@ -804,10 +804,12 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
data->dpm_table.sclk_table.count = 0;
for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
+ clk = min(allowed_vdd_sclk_table->entries[i].clk, data->sclk_cap);
+
if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
- allowed_vdd_sclk_table->entries[i].clk) {
+ clk) {
data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
- allowed_vdd_sclk_table->entries[i].clk;
+ clk;
data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0;
data->dpm_table.sclk_table.count++;
}
@@ -3000,6 +3002,25 @@ static int smu7_init_voltage_dependency_on_display_clock_table(struct pp_hwmgr *
return 0;
}
+static void smu7_set_sclk_cap(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+ data->sclk_cap = 0xffffffff;
+
+ if (hwmgr->od_enabled)
+ return;
+
+ /* R9 390X board: last sclk dpm level is unstable, use lower sclk */
+ if (adev->pdev->device == 0x67B0 &&
+ adev->pdev->subsystem_vendor == 0x1043)
+ data->sclk_cap = 104000; /* 1040 MHz */
+
+ if (data->sclk_cap != 0xffffffff)
+ dev_info(adev->dev, "sclk cap: %u kHz on quirky ASIC\n", data->sclk_cap * 10);
+}
+
static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
@@ -3011,6 +3032,7 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
return -ENOMEM;
hwmgr->backend = data;
+ smu7_set_sclk_cap(hwmgr);
smu7_patch_voltage_workaround(hwmgr);
smu7_init_dpm_defaults(hwmgr);
@@ -3894,7 +3916,7 @@ static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr,
/* Performance levels are arranged from low to high. */
performance_level->memory_clock = memory_clock;
- performance_level->engine_clock = engine_clock;
+ performance_level->engine_clock = min(engine_clock, data->sclk_cap);
pcie_gen_from_bios = visland_clk_info->ucPCIEGen;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
index d9e8b386bd4d3..66adabeab6a3a 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h
@@ -234,6 +234,7 @@ struct smu7_hwmgr {
uint32_t pcie_gen_cap;
uint32_t pcie_lane_cap;
uint32_t pcie_spc_cap;
+ uint32_t sclk_cap;
struct smu7_leakage_voltage vddc_leakage;
struct smu7_leakage_voltage vddci_leakage;
struct smu7_leakage_voltage vddcgfx_leakage;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 9/9] drm/amdgpu/uvd4.2: Don't initialize UVD 4.2 when DPM is disabled
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (7 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 8/9] drm/amd/pm/smu7: Add SCLK cap for quirky Hawaii board Timur Kristóf
@ 2026-03-29 16:03 ` Timur Kristóf
2026-03-30 15:52 ` [PATCH 0/9] Various SMU7 power management fixes Alex Deucher
9 siblings, 0 replies; 11+ messages in thread
From: Timur Kristóf @ 2026-03-29 16:03 UTC (permalink / raw)
To: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
Cc: Timur Kristóf
UVD 4.2 doesn't work at all when DPM is disabled because
the SMU is responsible for ungating it. So, Linux fails
to boot with CIK GPUs when using the amdgpu.dpm=0 parameter.
Fix this by returning -ENOENT from uvd_v4_2_early_init()
when amdgpu_dpm isn't enabled.
Note: amdgpu.dpm=0 is often suggested as a workaround
for issues and is useful for debugging.
Fixes: a2e73f56fa62 ("drm/amdgpu: Add support for CIK parts")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index 73ce3d211ed64..8a9ba2276275c 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -93,6 +93,11 @@ static void uvd_v4_2_ring_set_wptr(struct amdgpu_ring *ring)
static int uvd_v4_2_early_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+
+ /* UVD doesn't work without DPM, it needs DPM to ungate it. */
+ if (!amdgpu_dpm)
+ return -ENOENT;
+
adev->uvd.num_uvd_inst = 1;
uvd_v4_2_set_ring_funcs(adev);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 0/9] Various SMU7 power management fixes
2026-03-29 16:02 [PATCH 0/9] Various SMU7 power management fixes Timur Kristóf
` (8 preceding siblings ...)
2026-03-29 16:03 ` [PATCH 9/9] drm/amdgpu/uvd4.2: Don't initialize UVD 4.2 when DPM is disabled Timur Kristóf
@ 2026-03-30 15:52 ` Alex Deucher
9 siblings, 0 replies; 11+ messages in thread
From: Alex Deucher @ 2026-03-30 15:52 UTC (permalink / raw)
To: Timur Kristóf
Cc: amd-gfx, alexander.deucher, christian.koenig, harry.wentland
On Sun, Mar 29, 2026 at 12:03 PM Timur Kristóf <timur.kristof@gmail.com> wrote:
>
> This series fixes various issues that I found on two GPUs:
>
> R9 390X (Hawaii, Asus ROG branded):
> Add SCLK cap to fix stability issues, fix PCI ID typo.
> And a few minor fixes affecting CI GPUs.
>
> R9 M380 (Bonaire, found in an iMac from 2015):
> Disable MCLK switching, use highest MCLK.
>
> Additionally, fix possible black screen on boot caused by
> a non-functional implementation of the voltage dependency on
> the display clock. The fix affects all GPUs with SMU7,
> hopefully improving stability for CI, VI and Polaris GPUs.
>
> Looking forward to reviews and feedback!
Applied the series.
Thanks!
Alex
>
> Timur Kristóf (9):
> drm/amd/pm/ci: Use highest MCLK on CI when MCLK DPM is disabled
> drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs
> drm/amd/pm/smu7: Fix SMU7 voltage dependency on display clock
> drm/amd/pm/smu7: Remove non-functional SMU7 voltage dependency on DAL
> drm/amd/pm/ci: Fix powertune defaults for Hawaii 0x67B0
> drm/amd/pm/ci: Clear EnabledForActivity field for memory levels
> drm/amd/pm/ci: Fill DW8 fields from SMC
> drm/amd/pm/smu7: Add SCLK cap for quirky Hawaii board
> drm/amdgpu/uvd4.2: Don't initialize UVD 4.2 when DPM is disabled
>
> drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 5 +
> .../gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c | 15 +++
> .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 123 ++++++++++++++++--
> .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h | 1 +
> .../drm/amd/pm/powerplay/hwmgr/smu_helper.c | 84 ------------
> .../drm/amd/pm/powerplay/hwmgr/smu_helper.h | 2 -
> drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 2 +-
> .../drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 15 ++-
> 8 files changed, 142 insertions(+), 105 deletions(-)
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 11+ messages in thread