diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.h b/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.h index f2c001ef64e1..5c3e92f710b4 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.h +++ b/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.h @@ -36,10 +36,10 @@ /* * Bad address pfn : eeprom_umc_record.retired_row_pfn[39:0], - * nps mode: eeprom_umc_record.retired_row_pfn[47:40] + * nps mode: eeprom_umc_record.retired_row_pfn[46:40] */ #define EEPROM_RECORD_UMC_ADDR_MASK 0xFFFFFFFFFFULL -#define EEPROM_RECORD_UMC_NPS_MASK 0xFF0000000000ULL +#define EEPROM_RECORD_UMC_NPS_MASK 0x7F0000000000ULL #define EEPROM_RECORD_UMC_NPS_SHIFT 40 #define EEPROM_RECORD_UMC_NPS_MODE(RECORD) \ diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c index dd7a37163110..f59f0b6cad06 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c +++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c @@ -346,7 +346,7 @@ static bool ras_umc_check_retired_record(struct ras_core_context *ras_core, if (ras_umc->ip_func && ras_umc->ip_func->eeprom_record_to_nps_record) { ret = ras_umc->ip_func->eeprom_record_to_nps_record(ras_core, record, nps); if (ret) - RAS_DEV_WARN(ras_core->dev, + RAS_DEV_WARN_RATELIMITED(ras_core->dev, "Failed to adjust eeprom record, ret:%d", ret); } return false; diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc.h b/drivers/gpu/drm/amd/ras/rascore/ras_umc.h index 71b6703193f5..3d902b0d663a 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_umc.h +++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc.h @@ -46,6 +46,26 @@ #define UMC_ECC_NEW_DETECTED_TAG 0x1 #define UMC_INV_MEM_PFN (0xFFFFFFFFFFFFFFFF) +/* + * a flag to indicate v2 format channel index stored in eeprom + * + * v1: store channel index within a umc instance in eeprom + * range in UMC v12: 0 ~ 7 + * v2: store global channel index in eeprom + * range in UMC v12: 0 ~ 127 + * + * NOTE: it's better to store it in eeprom_table_record.mem_channel, + * but there is only 8 bits in mem_channel, and the channel number may + * increase in the future, we decide to save it in + * eeprom_table_record.retired_page. retired_page is useless in v2, + * we depend on eeprom_table_record.address instead of retired_page in v2. + * Only 48 bits are saved on eeprom, use bit 47 here. + * + * UMC_CHANNEL_IDX_V2 is replaced by nps value in cur_nps_retired_row_pfn + * in eeprom v3 format, so they have no conflict. + */ +#define UMC_CHANNEL_IDX_V2 BIT_ULL(47) + /* three column bits and one row bit in MCA address flip * in bad page retirement */ diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc_v12_0.c b/drivers/gpu/drm/amd/ras/rascore/ras_umc_v12_0.c index 2c442db1b2f4..6bf30dee8d17 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_umc_v12_0.c +++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc_v12_0.c @@ -460,16 +460,30 @@ static int convert_eeprom_record_to_nps_addr(struct ras_core_context *ras_core, static int umc_v12_0_eeprom_record_to_nps_record(struct ras_core_context *ras_core, struct eeprom_umc_record *record, uint32_t nps) { - uint64_t pa = 0; + uint64_t ch_idx_v2, pa = 0; + uint32_t save_nps; int ret = 0; - if (nps == EEPROM_RECORD_UMC_NPS_MODE(record) && !ras_fw_eeprom_supported(ras_core)) { - record->cur_nps_retired_row_pfn = EEPROM_RECORD_UMC_ADDR_PFN(record); - } else { - ret = convert_eeprom_record_to_nps_addr(ras_core, + save_nps = EEPROM_RECORD_UMC_NPS_MODE(record); + /* eeprom v2 has no stored nps, always convert if the flag is set */ + ch_idx_v2 = record->retired_row_pfn & UMC_CHANNEL_IDX_V2; + + if (save_nps || ch_idx_v2) { + if ((nps == save_nps) && !ras_fw_eeprom_supported(ras_core)) { + record->cur_nps_retired_row_pfn = + EEPROM_RECORD_UMC_ADDR_PFN(record); + } else { + ret = convert_eeprom_record_to_nps_addr(ras_core, record, &pa, nps); - if (!ret) - record->cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(pa); + if (!ret) + record->cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(pa); + } + } else { + /* old eeprom data format, the scope of channel index is + * limited to umc instance + */ + /* TODO */ + ret = -EOPNOTSUPP; } record->cur_nps = nps;