Replace the simple exact-match loop in emit_clk_levels with a two-pass approach: the first pass checks whether the current frequency matches any DPM level exactly and also tracks the closest level by absolute frequency difference. The second pass emits the levels, marking the exact match if found, otherwise the closest level.
The SMU reports time-filtered average frequencies that often do not match any DPM table entry exactly. Without this fallback, MCLK, FCLK and other clocks show DPM levels but never display the * marker, breaking userspace tools that rely on it to identify the active frequency. Also uses reverse DPM index for SMU_MCLK since MemPstateTable stores levels high-to-low. Signed-off-by: Priya Hosur <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> --- .../drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c index 206bfa906ad6..45b0baeb194c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c @@ -1218,14 +1218,46 @@ static int smu_v14_0_0_emit_clk_levels(struct smu_context *smu, if (ret) return ret; - for (i = 0; i < count; i++) { - idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i; - ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, idx, &value); - if (ret) - return ret; + /* + * Try exact match first. If the SMU reports a time-averaged + * frequency that doesn't match any DPM level exactly, fall + * back to marking the closest DPM level. + */ + { + int closest_idx = 0; + uint32_t closest_diff = U32_MAX; + uint32_t diff; + + for (i = 0; i < count; i++) { + idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, idx, &value); + if (ret) + return ret; + + if (cur_value == value) { + closest_idx = i; + break; + } - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value, - cur_value == value ? "*" : ""); + diff = abs((int)cur_value - (int)value); + if (diff < closest_diff) { + closest_diff = diff; + closest_idx = i; + } else if (diff > closest_diff) { + break; + } + } + + for (i = 0; i < count; i++) { + idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, idx, &value); + if (ret) + return ret; + + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", + i, value, + i == closest_idx ? "*" : ""); + } } break; case SMU_DCEFCLK: -- 2.43.0
