From: Asad Kamal <[email protected]>

Add emit clock support and fetching other metrics data like temperature,
clock for smu_v15_0_8

v2: Use umc count for hbm stack temperature (Lijo)

v3: Use correct logic for hbm stacks (Lijo)

Signed-off-by: Asad Kamal <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c  | 198 ++++++++++++++++++
 1 file changed, 198 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index d7d40985b0b71..9b48c258b1f20 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -311,6 +311,203 @@ static int smu_v15_0_8_get_metrics_table_internal(struct 
smu_context *smu, uint3
        return ret;
 }
 
+static int smu_v15_0_8_get_smu_metrics_data(struct smu_context *smu,
+                                           MetricsMember_t member, uint32_t 
*value)
+{
+       struct smu_table_context *smu_table = &smu->smu_table;
+       MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
+       struct amdgpu_device *adev = smu->adev;
+       int ret, xcc_id;
+
+       ret = smu_v15_0_8_get_metrics_table_internal(smu, 10, NULL);
+       if (ret)
+               return ret;
+
+       switch (member) {
+       case METRICS_CURR_GFXCLK:
+       case METRICS_AVERAGE_GFXCLK:
+                       xcc_id = GET_INST(GC, 0);
+                       *value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
+               break;
+       case METRICS_CURR_SOCCLK:
+       case METRICS_AVERAGE_SOCCLK:
+               *value = SMUQ10_ROUND(metrics->SocclkFrequency[0]);
+               break;
+       case METRICS_CURR_UCLK:
+       case METRICS_AVERAGE_UCLK:
+               *value = SMUQ10_ROUND(metrics->UclkFrequency[0]);
+               break;
+       case METRICS_CURR_VCLK:
+               *value = SMUQ10_ROUND(metrics->VclkFrequency[0]);
+               break;
+       case METRICS_CURR_DCLK:
+               *value = SMUQ10_ROUND(metrics->DclkFrequency[0]);
+               break;
+       case METRICS_CURR_FCLK:
+               *value = SMUQ10_ROUND(metrics->FclkFrequency[0]);
+               break;
+       case METRICS_AVERAGE_GFXACTIVITY:
+               *value = SMUQ10_ROUND(metrics->SocketGfxBusy);
+               break;
+       case METRICS_AVERAGE_MEMACTIVITY:
+               *value = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
+               break;
+       case METRICS_CURR_SOCKETPOWER:
+               *value = SMUQ10_ROUND(metrics->SocketPower) << 8;
+               break;
+       case METRICS_TEMPERATURE_HOTSPOT:
+               *value = SMUQ10_ROUND(metrics->MaxSocketTemperature) *
+                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+               break;
+       case METRICS_TEMPERATURE_MEM:
+       {
+               struct amdgpu_device *adev = smu->adev;
+               u32 max_hbm_temp = 0;
+
+               /* Find max temperature across all HBM stacks */
+               if (adev->umc.active_mask) {
+                       u64 mask = adev->umc.active_mask;
+                       int stack_idx;
+
+                       for_each_hbm_stack(stack_idx, mask) {
+                               u32 temp;
+
+                               if (!hbm_stack_mask_valid(mask))
+                                       continue;
+
+                               temp = 
SMUQ10_ROUND(metrics->HbmTemperature[stack_idx]);
+                               if (temp > max_hbm_temp)
+                                       max_hbm_temp = temp;
+                       }
+               }
+               *value = max_hbm_temp * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+               break;
+       }
+       /* This is the max of all VRs and not just SOC VR.
+        */
+       case METRICS_TEMPERATURE_VRSOC:
+               *value = SMUQ10_ROUND(metrics->MaxVrTemperature) *
+                        SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+               break;
+       default:
+               *value = UINT_MAX;
+               break;
+       }
+
+       return 0;
+}
+
+static int smu_v15_0_8_get_current_clk_freq_by_table(struct smu_context *smu,
+                                                    enum smu_clk_type clk_type,
+                                                    uint32_t *value)
+{
+       MetricsMember_t member_type;
+
+       if (!value)
+               return -EINVAL;
+
+       switch (clk_type) {
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               member_type = METRICS_CURR_GFXCLK;
+               break;
+       case SMU_UCLK:
+       case SMU_MCLK:
+               member_type = METRICS_CURR_UCLK;
+               break;
+       case SMU_SOCCLK:
+               member_type = METRICS_CURR_SOCCLK;
+               break;
+       case SMU_VCLK:
+               member_type = METRICS_CURR_VCLK;
+               break;
+       case SMU_DCLK:
+               member_type = METRICS_CURR_DCLK;
+               break;
+       case SMU_FCLK:
+               member_type = METRICS_CURR_FCLK;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return smu_v15_0_8_get_smu_metrics_data(smu, member_type, value);
+}
+
+static int smu_v15_0_8_emit_clk_levels(struct smu_context *smu,
+                                      enum smu_clk_type type, char *buf,
+                                      int *offset)
+{
+       struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+       struct smu_15_0_dpm_context *dpm_context;
+       struct smu_dpm_table *single_dpm_table = NULL;
+       struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+       int ret, now, size = *offset;
+
+       if (amdgpu_ras_intr_triggered()) {
+               sysfs_emit_at(buf, size, "unavailable\n");
+               return -EBUSY;
+       }
+
+       dpm_context = smu_dpm->dpm_context;
+
+       switch (type) {
+       case SMU_OD_SCLK:
+               size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
+               size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+                                     pstate_table->gfxclk_pstate.curr.min,
+                                     pstate_table->gfxclk_pstate.curr.max);
+               break;
+       case SMU_OD_MCLK:
+               size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK");
+               size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+                                     pstate_table->uclk_pstate.curr.min,
+                                     pstate_table->uclk_pstate.curr.max);
+               break;
+       case SMU_SCLK:
+       case SMU_GFXCLK:
+               single_dpm_table = &dpm_context->dpm_tables.gfx_table;
+               break;
+       case SMU_MCLK:
+       case SMU_UCLK:
+               single_dpm_table = &dpm_context->dpm_tables.uclk_table;
+               break;
+       case SMU_SOCCLK:
+               single_dpm_table = &dpm_context->dpm_tables.soc_table;
+               break;
+       case SMU_FCLK:
+               single_dpm_table = &dpm_context->dpm_tables.fclk_table;
+               break;
+       case SMU_VCLK:
+               single_dpm_table = &dpm_context->dpm_tables.vclk_table;
+               break;
+       case SMU_DCLK:
+               single_dpm_table = &dpm_context->dpm_tables.dclk_table;
+               break;
+       default:
+               break;
+       }
+
+       if (single_dpm_table) {
+               ret = smu_v15_0_8_get_current_clk_freq_by_table(smu, type, 
&now);
+               if (ret) {
+                       dev_err(smu->adev->dev,
+                               "Attempt to get current clk Failed!");
+                       return ret;
+               }
+               ret = smu_cmn_print_dpm_clk_levels(smu, single_dpm_table, now,
+                                                  buf, offset);
+               if (ret < 0)
+                       return ret;
+
+               return 0;
+       }
+
+       *offset = size;
+
+       return 0;
+}
+
 static int smu_v15_0_8_get_dpm_ultimate_freq(struct smu_context *smu,
                                             enum smu_clk_type clk_type,
                                             uint32_t *min, uint32_t *max)
@@ -1206,6 +1403,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = 
{
        .get_unique_id = smu_v15_0_8_get_unique_id,
        .get_power_limit = smu_v15_0_8_get_power_limit,
        .set_power_limit = smu_v15_0_set_power_limit,
+       .emit_clk_levels = smu_v15_0_8_emit_clk_levels,
 };
 
 static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
-- 
2.53.0

Reply via email to