diff options
Diffstat (limited to 'drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c')
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index fb130409309c..619aee51b123 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -83,6 +83,12 @@ #define SUPPORT_ECCTABLE_SMU_VERSION 0x00442a00 /* + * SMU support mca_ceumc_addr in ECCTABLE since version 68.55.0, + * use this to check mca_ceumc_addr record whether support + */ +#define SUPPORT_ECCTABLE_V2_SMU_VERSION 0x00443700 + +/* * SMU support BAD CHENNEL info MSG since version 68.51.00, * use this to check ECCTALE feature whether support */ @@ -549,12 +555,13 @@ static int aldebaran_get_clk_table(struct smu_context *smu, struct pp_clock_levels_with_latency *clocks, struct smu_13_0_dpm_table *dpm_table) { - int i, count; + uint32_t i; - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = count; + clocks->num_levels = min_t(uint32_t, + dpm_table->count, + (uint32_t)PP_MAX_CLOCK_LEVELS); - for (i = 0; i < count; i++) { + for (i = 0; i < clocks->num_levels; i++) { clocks->data[i].clocks_in_khz = dpm_table->dpm_levels[i].value * 1000; clocks->data[i].latency_in_us = 0; @@ -739,7 +746,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, struct smu_13_0_dpm_table *single_dpm_table; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; struct smu_13_0_dpm_context *dpm_context = NULL; - uint32_t display_levels; + int display_levels; uint32_t freq_values[3] = {0}; uint32_t min_clk, max_clk; @@ -771,7 +778,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, return ret; } - display_levels = clocks.num_levels; + display_levels = (clocks.num_levels == 1) ? 1 : 2; min_clk = pstate_table->gfxclk_pstate.curr.min; max_clk = pstate_table->gfxclk_pstate.curr.max; @@ -781,30 +788,20 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, /* fine-grained dpm has only 2 levels */ if (now > min_clk && now < max_clk) { - display_levels = clocks.num_levels + 1; + display_levels++; freq_values[2] = max_clk; freq_values[1] = now; } - /* - * For DPM disabled case, there will be only one clock level. - * And it's safe to assume that is always the current clock. - */ - if (display_levels == clocks.num_levels) { - for (i = 0; i < clocks.num_levels; i++) - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, - freq_values[i], - (clocks.num_levels == 1) ? - "*" : - (aldebaran_freqs_in_same_level( - freq_values[i], now) ? - "*" : - "")); - } else { - for (i = 0; i < display_levels; i++) - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, - freq_values[i], i == 1 ? "*" : ""); - } + for (i = 0; i < display_levels; i++) + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, + freq_values[i], + (display_levels == 1) ? + "*" : + (aldebaran_freqs_in_same_level( + freq_values[i], now) ? + "*" : + "")); break; @@ -1803,7 +1800,8 @@ static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_3); } -static int aldebaran_check_ecc_table_support(struct smu_context *smu) +static int aldebaran_check_ecc_table_support(struct smu_context *smu, + int *ecctable_version) { uint32_t if_version = 0xff, smu_version = 0xff; int ret = 0; @@ -1816,6 +1814,11 @@ static int aldebaran_check_ecc_table_support(struct smu_context *smu) if (smu_version < SUPPORT_ECCTABLE_SMU_VERSION) ret = -EOPNOTSUPP; + else if (smu_version >= SUPPORT_ECCTABLE_SMU_VERSION && + smu_version < SUPPORT_ECCTABLE_V2_SMU_VERSION) + *ecctable_version = 1; + else + *ecctable_version = 2; return ret; } @@ -1827,9 +1830,10 @@ static ssize_t aldebaran_get_ecc_info(struct smu_context *smu, EccInfoTable_t *ecc_table = NULL; struct ecc_info_per_ch *ecc_info_per_channel = NULL; int i, ret = 0; + int table_version = 0; struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table; - ret = aldebaran_check_ecc_table_support(smu); + ret = aldebaran_check_ecc_table_support(smu, &table_version); if (ret) return ret; @@ -1845,16 +1849,33 @@ static ssize_t aldebaran_get_ecc_info(struct smu_context *smu, ecc_table = (EccInfoTable_t *)smu_table->ecc_table; - for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) { - ecc_info_per_channel = &(eccinfo->ecc[i]); - ecc_info_per_channel->ce_count_lo_chip = - ecc_table->EccInfo[i].ce_count_lo_chip; - ecc_info_per_channel->ce_count_hi_chip = - ecc_table->EccInfo[i].ce_count_hi_chip; - ecc_info_per_channel->mca_umc_status = - ecc_table->EccInfo[i].mca_umc_status; - ecc_info_per_channel->mca_umc_addr = - ecc_table->EccInfo[i].mca_umc_addr; + if (table_version == 1) { + for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) { + ecc_info_per_channel = &(eccinfo->ecc[i]); + ecc_info_per_channel->ce_count_lo_chip = + ecc_table->EccInfo[i].ce_count_lo_chip; + ecc_info_per_channel->ce_count_hi_chip = + ecc_table->EccInfo[i].ce_count_hi_chip; + ecc_info_per_channel->mca_umc_status = + ecc_table->EccInfo[i].mca_umc_status; + ecc_info_per_channel->mca_umc_addr = + ecc_table->EccInfo[i].mca_umc_addr; + } + } else if (table_version == 2) { + for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) { + ecc_info_per_channel = &(eccinfo->ecc[i]); + ecc_info_per_channel->ce_count_lo_chip = + ecc_table->EccInfo_V2[i].ce_count_lo_chip; + ecc_info_per_channel->ce_count_hi_chip = + ecc_table->EccInfo_V2[i].ce_count_hi_chip; + ecc_info_per_channel->mca_umc_status = + ecc_table->EccInfo_V2[i].mca_umc_status; + ecc_info_per_channel->mca_umc_addr = + ecc_table->EccInfo_V2[i].mca_umc_addr; + ecc_info_per_channel->mca_ceumc_addr = + ecc_table->EccInfo_V2[i].mca_ceumc_addr; + } + eccinfo->record_ce_addr_supported = 1; } return ret; @@ -2117,4 +2138,5 @@ void aldebaran_set_ppt_funcs(struct smu_context *smu) smu->clock_map = aldebaran_clk_map; smu->feature_map = aldebaran_feature_mask_map; smu->table_map = aldebaran_table_map; + smu_v13_0_set_smu_mailbox_registers(smu); } |