On Wed, Jun 17, 2026 at 6:49 AM Priya Hosur <[email protected]> wrote: > > SmuMetrics_t has no DclkFrequency field but DCLK and VCLK have > separate DPM clock tables with different frequencies at each level. > > Introduce smu_v14_0_0_find_clk_level(), a shared helper that > finds the closest DPM level for a given target frequency in a > frequency array. > > For METRICS_AVERAGE_DCLK, use the helper to find the DPM level > whose VCLK frequency matches the reported VclkFrequency and > return the DCLK frequency at that same level index, since both > clocks share the same level count (VcnClkLevelsEnabled / > Vcn0ClkLevelsEnabled). > > The original code returned 0 for METRICS_AVERAGE_DCLK, which broke > the active-level marker in pp_dpm_dclk entirely. > > Signed-off-by: Priya Hosur <[email protected]>
Series is: Acked-by: Alex Deucher <[email protected]> > --- > .../drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c | 52 +++++++++++++++++++ > 1 file changed, 52 insertions(+) > > 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 2fe006de927a..b206a4d0376b 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 > @@ -260,6 +260,35 @@ static int smu_v14_0_0_system_features_control(struct > smu_context *smu, bool en) > return ret; > } > > +/** > + * smu_v14_0_0_find_clk_level - find the closest DPM level for a frequency > + * @freqs: array of frequencies (one per DPM level) > + * @count: number of valid entries in @freqs > + * @target: the frequency to match > + * > + * Returns the index of the DPM level whose frequency is closest to @target. > + * If an exact match exists it is preferred; otherwise the nearest level by > + * absolute difference is returned. > + */ > +static uint8_t smu_v14_0_0_find_clk_level(const uint32_t *freqs, uint8_t > count, > + uint32_t target) > +{ > + uint8_t i, closest = 0; > + uint32_t best_diff = U32_MAX; > + > + for (i = 0; i < count; i++) { > + uint32_t diff = abs((int)target - (int)freqs[i]); > + > + if (diff < best_diff) { > + best_diff = diff; > + closest = i; > + } > + if (freqs[i] == target) > + return i; > + } > + return closest; > +} > + > static int smu_v14_0_0_get_smu_metrics_data(struct smu_context *smu, > MetricsMember_t member, > uint32_t *value) > @@ -284,7 +313,30 @@ static int smu_v14_0_0_get_smu_metrics_data(struct > smu_context *smu, > *value = metrics->VclkFrequency; > break; > case METRICS_AVERAGE_DCLK: > + /* > + * SmuMetrics_t has no DclkFrequency field. DCLK and VCLK > + * share the same DPM level count, so find the DPM level > + * whose VCLK matches the reported VclkFrequency and return > + * the DCLK frequency at that level. > + */ > *value = 0; > + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == > IP_VERSION(14, 0, 1)) { > + DpmClocks_t_v14_0_1 *clk_table = > smu->smu_table.clocks_table; > + uint8_t lvl = smu_v14_0_0_find_clk_level( > + clk_table->VClocks0, > + clk_table->Vcn0ClkLevelsEnabled, > + metrics->VclkFrequency); > + > + *value = clk_table->DClocks0[lvl]; > + } else { > + DpmClocks_t *clk_table = smu->smu_table.clocks_table; > + uint8_t lvl = smu_v14_0_0_find_clk_level( > + clk_table->VClocks, > + clk_table->VcnClkLevelsEnabled, > + metrics->VclkFrequency); > + > + *value = clk_table->DClocks[lvl]; > + } > break; > case METRICS_AVERAGE_UCLK: > *value = metrics->MemclkFrequency; > -- > 2.43.0 >
