Replace the simple exact-match loop in emit_clk_levels with a call
to smu_v14_0_0_find_clk_level() introduced in patch 1.  The helper
already handles both exact and closest-match semantics.

Build a stack-local frequency table from the DPM levels (using
reverse index for SMU_MCLK since MemPstateTable stores levels
high-to-low), then call the helper once to find the active level.

The SMU reports time-filtered average frequencies that often do not
match any DPM table entry exactly.  Without closest-match 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.

Signed-off-by: Priya Hosur <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c  | 29 ++++++++++++++-----
 1 file changed, 22 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 f273b95928c9..9efeaedbe317 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
@@ -1243,14 +1243,29 @@ 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;
+               /*
+                * Build a frequency table and use find_clk_level() to
+                * locate the closest DPM level.  The SMU often reports
+                * time-averaged frequencies that do not match any DPM
+                * entry exactly.
+                */
+               {
+                       uint32_t freqs[NUM_SOCCLK_DPM_LEVELS];
+                       int active;
+
+                       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, &freqs[i]);
+                               if (ret)
+                                       return ret;
+                       }
+
+                       active = smu_v14_0_0_find_clk_level(freqs, count, 
cur_value);
 
-                       size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, 
value,
-                                             cur_value == value ? "*" : "");
+                       for (i = 0; i < count; i++)
+                               size += sysfs_emit_at(buf, size, "%d: %uMhz 
%s\n",
+                                                     i, freqs[i],
+                                                     i == active ? "*" : "");
                }
                break;
        case SMU_DCEFCLK:
-- 
2.43.0

Reply via email to