Commit 86c8236e authored by Xiaojian Du's avatar Xiaojian Du Committed by Alex Deucher

drm/amd/pm: add support for new smu metrics table for vangogh

This patch is to add support for new smu metrics table for vangogh.
It will support new and legacy smu metrics table in the meanwhile.
New pmfw version is 4.63.36.00, and new smu interface version is #3.

v1: check smu pmfw version to determine to use new or legacy smu metrics
table

v2: check smu interface version to determine to use new or legacy smu
metrics table

v3: revise wrong symbol
Signed-off-by: default avatarXiaojian Du <Xiaojian.Du@amd.com>
Reviewed-by: default avatarKevin Wang <kevin1.wang@amd.com>
Reviewed-by: default avatarHuang Rui <ray.huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f4994be2
......@@ -194,18 +194,34 @@ static int vangogh_tables_init(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *tables = smu_table->tables;
struct amdgpu_device *adev = smu->adev;
uint32_t if_version;
uint32_t ret = 0;
ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
if (ret) {
dev_err(adev->dev, "Failed to get smu if version!\n");
goto err0_out;
}
SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
if (if_version < 0x3) {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_legacy_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_legacy_t), GFP_KERNEL);
} else {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
}
if (!smu_table->metrics_table)
goto err0_out;
smu_table->metrics_time = 0;
......@@ -235,13 +251,12 @@ static int vangogh_tables_init(struct smu_context *smu)
return -ENOMEM;
}
static int vangogh_get_smu_metrics_data(struct smu_context *smu,
static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
{
struct smu_table_context *smu_table = &smu->smu_table;
SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
SmuMetrics_legacy_t *metrics = (SmuMetrics_legacy_t *)smu_table->metrics_table;
int ret = 0;
mutex_lock(&smu->metrics_lock);
......@@ -311,6 +326,103 @@ static int vangogh_get_smu_metrics_data(struct smu_context *smu,
return ret;
}
static int vangogh_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
{
struct smu_table_context *smu_table = &smu->smu_table;
SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
int ret = 0;
mutex_lock(&smu->metrics_lock);
ret = smu_cmn_get_metrics_table_locked(smu,
NULL,
false);
if (ret) {
mutex_unlock(&smu->metrics_lock);
return ret;
}
switch (member) {
case METRICS_AVERAGE_GFXCLK:
*value = metrics->Current.GfxclkFrequency;
break;
case METRICS_AVERAGE_SOCCLK:
*value = metrics->Current.SocclkFrequency;
break;
case METRICS_AVERAGE_VCLK:
*value = metrics->Current.VclkFrequency;
break;
case METRICS_AVERAGE_DCLK:
*value = metrics->Current.DclkFrequency;
break;
case METRICS_AVERAGE_UCLK:
*value = metrics->Current.MemclkFrequency;
break;
case METRICS_AVERAGE_GFXACTIVITY:
*value = metrics->Current.GfxActivity;
break;
case METRICS_AVERAGE_VCNACTIVITY:
*value = metrics->Current.UvdActivity;
break;
case METRICS_AVERAGE_SOCKETPOWER:
*value = (metrics->Current.CurrentSocketPower << 8) /
1000;
break;
case METRICS_TEMPERATURE_EDGE:
*value = metrics->Current.GfxTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_HOTSPOT:
*value = metrics->Current.SocTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_THROTTLER_STATUS:
*value = metrics->Current.ThrottlerStatus;
break;
case METRICS_VOLTAGE_VDDGFX:
*value = metrics->Current.Voltage[2];
break;
case METRICS_VOLTAGE_VDDSOC:
*value = metrics->Current.Voltage[1];
break;
case METRICS_AVERAGE_CPUCLK:
memcpy(value, &metrics->Current.CoreFrequency[0],
smu->cpu_core_num * sizeof(uint16_t));
break;
default:
*value = UINT_MAX;
break;
}
mutex_unlock(&smu->metrics_lock);
return ret;
}
static int vangogh_common_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
{
struct amdgpu_device *adev = smu->adev;
uint32_t if_version;
int ret = 0;
ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
if (ret) {
dev_err(adev->dev, "Failed to get smu if version!\n");
return ret;
}
if (if_version < 0x3)
ret = vangogh_get_legacy_smu_metrics_data(smu, member, value);
else
ret = vangogh_get_smu_metrics_data(smu, member, value);
return ret;
}
static int vangogh_allocate_dpm_context(struct smu_context *smu)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
......@@ -447,11 +559,11 @@ static int vangogh_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_typ
return 0;
}
static int vangogh_print_clk_levels(struct smu_context *smu,
static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
DpmClocks_t *clk_table = smu->smu_table.clocks_table;
SmuMetrics_t metrics;
SmuMetrics_legacy_t metrics;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
int i, size = 0, ret = 0;
uint32_t cur_value = 0, value = 0, count = 0;
......@@ -546,6 +658,126 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
return size;
}
static int vangogh_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
DpmClocks_t *clk_table = smu->smu_table.clocks_table;
SmuMetrics_t metrics;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
int i, size = 0, ret = 0;
uint32_t cur_value = 0, value = 0, count = 0;
bool cur_value_match_level = false;
memset(&metrics, 0, sizeof(metrics));
ret = smu_cmn_get_metrics_table(smu, &metrics, false);
if (ret)
return ret;
switch (clk_type) {
case SMU_OD_SCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
size = sprintf(buf, "%s:\n", "OD_SCLK");
size += sprintf(buf + size, "0: %10uMhz\n",
(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
size += sprintf(buf + size, "1: %10uMhz\n",
(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
}
break;
case SMU_OD_CCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
size = sprintf(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select);
size += sprintf(buf + size, "0: %10uMhz\n",
(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
size += sprintf(buf + size, "1: %10uMhz\n",
(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
}
break;
case SMU_OD_RANGE:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
size = sprintf(buf, "%s:\n", "OD_RANGE");
size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
size += sprintf(buf + size, "CCLK: %7uMhz %10uMhz\n",
smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
}
break;
case SMU_SOCCLK:
/* the level 3 ~ 6 of socclk use the same frequency for vangogh */
count = clk_table->NumSocClkLevelsEnabled;
cur_value = metrics.Current.SocclkFrequency;
break;
case SMU_VCLK:
count = clk_table->VcnClkLevelsEnabled;
cur_value = metrics.Current.VclkFrequency;
break;
case SMU_DCLK:
count = clk_table->VcnClkLevelsEnabled;
cur_value = metrics.Current.DclkFrequency;
break;
case SMU_MCLK:
count = clk_table->NumDfPstatesEnabled;
cur_value = metrics.Current.MemclkFrequency;
break;
case SMU_FCLK:
count = clk_table->NumDfPstatesEnabled;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
if (ret)
return ret;
break;
default:
break;
}
switch (clk_type) {
case SMU_SOCCLK:
case SMU_VCLK:
case SMU_DCLK:
case SMU_MCLK:
case SMU_FCLK:
for (i = 0; i < count; i++) {
ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
if (ret)
return ret;
if (!value)
continue;
size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
if (cur_value == value)
cur_value_match_level = true;
}
if (!cur_value_match_level)
size += sprintf(buf + size, " %uMhz *\n", cur_value);
break;
default:
break;
}
return size;
}
static int vangogh_common_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
struct amdgpu_device *adev = smu->adev;
uint32_t if_version;
int ret = 0;
ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
if (ret) {
dev_err(adev->dev, "Failed to get smu if version!\n");
return ret;
}
if (if_version < 0x3)
ret = vangogh_print_legacy_clk_levels(smu, clk_type, buf);
else
ret = vangogh_print_clk_levels(smu, clk_type, buf);
return ret;
}
static int vangogh_get_profiling_clk_mask(struct smu_context *smu,
enum amd_dpm_forced_level level,
uint32_t *vclk_mask,
......@@ -1278,57 +1510,57 @@ static int vangogh_read_sensor(struct smu_context *smu,
mutex_lock(&smu->sensor_lock);
switch (sensor) {
case AMDGPU_PP_SENSOR_GPU_LOAD:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_AVERAGE_GFXACTIVITY,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_AVERAGE_SOCKETPOWER,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_TEMPERATURE_EDGE,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_TEMPERATURE_HOTSPOT,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_AVERAGE_UCLK,
(uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_AVERAGE_GFXCLK,
(uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDGFX:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_VOLTAGE_VDDGFX,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDNB:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_VOLTAGE_VDDSOC,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_CPU_CLK:
ret = vangogh_get_smu_metrics_data(smu,
ret = vangogh_common_get_smu_metrics_data(smu,
METRICS_AVERAGE_CPUCLK,
(uint32_t *)data);
*size = smu->cpu_core_num * sizeof(uint16_t);
......@@ -1402,13 +1634,13 @@ static int vangogh_set_watermarks_table(struct smu_context *smu,
return 0;
}
static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu,
void **table)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct gpu_metrics_v2_1 *gpu_metrics =
(struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table;
SmuMetrics_t metrics;
SmuMetrics_legacy_t metrics;
int ret = 0;
ret = smu_cmn_get_metrics_table(smu, &metrics, true);
......@@ -1421,9 +1653,8 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->temperature_soc = metrics.SocTemperature;
memcpy(&gpu_metrics->temperature_core[0],
&metrics.CoreTemperature[0],
sizeof(uint16_t) * 8);
sizeof(uint16_t) * 4);
gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
gpu_metrics->average_gfx_activity = metrics.GfxActivity;
gpu_metrics->average_mm_activity = metrics.UvdActivity;
......@@ -1434,7 +1665,7 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_gfx_power = metrics.Power[2];
memcpy(&gpu_metrics->average_core_power[0],
&metrics.CorePower[0],
sizeof(uint16_t) * 8);
sizeof(uint16_t) * 4);
gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
......@@ -1445,9 +1676,8 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
memcpy(&gpu_metrics->current_coreclk[0],
&metrics.CoreFrequency[0],
sizeof(uint16_t) * 8);
sizeof(uint16_t) * 4);
gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
gpu_metrics->throttle_status = metrics.ThrottlerStatus;
......@@ -1458,6 +1688,88 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v2_1);
}
static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
void **table)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct gpu_metrics_v2_1 *gpu_metrics =
(struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table;
SmuMetrics_t metrics;
int ret = 0;
ret = smu_cmn_get_metrics_table(smu, &metrics, true);
if (ret)
return ret;
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1);
gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
memcpy(&gpu_metrics->temperature_core[0],
&metrics.Current.CoreTemperature[0],
sizeof(uint16_t) * 4);
gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
gpu_metrics->average_cpu_power = metrics.Current.Power[0];
gpu_metrics->average_soc_power = metrics.Current.Power[1];
gpu_metrics->average_gfx_power = metrics.Current.Power[2];
memcpy(&gpu_metrics->average_core_power[0],
&metrics.Average.CorePower[0],
sizeof(uint16_t) * 4);
gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
memcpy(&gpu_metrics->current_coreclk[0],
&metrics.Current.CoreFrequency[0],
sizeof(uint16_t) * 4);
gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
*table = (void *)gpu_metrics;
return sizeof(struct gpu_metrics_v2_1);
}
static ssize_t vangogh_common_get_gpu_metrics(struct smu_context *smu,
void **table)
{
struct amdgpu_device *adev = smu->adev;
uint32_t if_version;
int ret = 0;
ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
if (ret) {
dev_err(adev->dev, "Failed to get smu if version!\n");
return ret;
}
if (if_version < 0x3)
ret = vangogh_get_legacy_gpu_metrics(smu, table);
else
ret = vangogh_get_gpu_metrics(smu, table);
return ret;
}
static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
long input[], uint32_t size)
{
......@@ -1876,9 +2188,9 @@ static const struct pptable_funcs vangogh_ppt_funcs = {
.set_watermarks_table = vangogh_set_watermarks_table,
.set_driver_table_location = smu_v11_0_set_driver_table_location,
.interrupt_work = smu_v11_0_interrupt_work,
.get_gpu_metrics = vangogh_get_gpu_metrics,
.get_gpu_metrics = vangogh_common_get_gpu_metrics,
.od_edit_dpm_table = vangogh_od_edit_dpm_table,
.print_clk_levels = vangogh_print_clk_levels,
.print_clk_levels = vangogh_common_print_clk_levels,
.set_default_dpm_table = vangogh_set_default_dpm_tables,
.set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
.system_features_control = vangogh_system_features_control,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment