mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
drm/amd/ras: move some umc v12 specific functions to ras_umc.c
So we can reuse these functions across different ASICs. In order to simplify code, rename some functions as well. Signed-off-by: Tao Zhou <tao.zhou1@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
4438d30cc0
commit
2844ade998
|
|
@ -82,7 +82,7 @@ static const struct ras_umc_ip_func *ras_umc_get_ip_func(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int ras_umc_psp_convert_ma_to_pa(struct ras_core_context *ras_core,
|
||||
int ras_umc_psp_ma2pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *in, struct umc_phy_addr *out,
|
||||
uint32_t nps)
|
||||
{
|
||||
|
|
@ -307,6 +307,95 @@ int ras_umc_log_bad_bank(struct ras_core_context *ras_core, struct ras_bank_ecc
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ras_umc_ma2pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
|
||||
uint32_t nps)
|
||||
{
|
||||
struct ras_umc *ras_umc = &ras_core->ras_umc;
|
||||
int ret;
|
||||
|
||||
if (ras_psp_check_supported_cmd(ras_core, RAS_TA_CMD_ID__QUERY_ADDRESS)) {
|
||||
ret = ras_umc_psp_ma2pa(ras_core, addr_in, addr_out, nps);
|
||||
} else {
|
||||
if (ras_umc->ip_func && ras_umc->ip_func->ma2pa) {
|
||||
ret = ras_umc->ip_func->ma2pa(ras_core, addr_in, addr_out, nps);
|
||||
} else {
|
||||
RAS_DEV_ERR(ras_core->dev, "ma2pa is not supported!\n");
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ras_umc_eeprom_rec2nps_addr(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint64_t *pa, uint32_t nps)
|
||||
{
|
||||
struct device_system_info dev_info = {0};
|
||||
struct umc_mca_addr addr_in;
|
||||
struct umc_phy_addr addr_out;
|
||||
struct ras_umc *ras_umc = &ras_core->ras_umc;
|
||||
int ret;
|
||||
|
||||
memset(&addr_in, 0, sizeof(addr_in));
|
||||
memset(&addr_out, 0, sizeof(addr_out));
|
||||
|
||||
ras_core_get_device_system_info(ras_core, &dev_info);
|
||||
|
||||
addr_in.err_addr = record->address;
|
||||
addr_in.ch_inst = record->mem_channel;
|
||||
addr_in.umc_inst = record->mcumc_id;
|
||||
addr_in.node_inst = UMC_INV_AID_NODE;
|
||||
addr_in.socket_id = dev_info.socket_id;
|
||||
|
||||
ret = ras_umc_ma2pa(ras_core, &addr_in, &addr_out, nps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ras_umc->ip_func && ras_umc->ip_func->nps_pa_to_row_pa) {
|
||||
*pa = ras_umc->ip_func->nps_pa_to_row_pa(ras_core, addr_out.pa,
|
||||
nps, false);
|
||||
} else {
|
||||
RAS_DEV_ERR(ras_core->dev, "nps_pa_to_row_pa is not supported!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ras_umc_eeprom_rec2nps_rec(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint32_t nps)
|
||||
{
|
||||
uint64_t ch_idx_v2, pa = 0;
|
||||
uint32_t save_nps;
|
||||
int ret = 0;
|
||||
|
||||
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 = ras_umc_eeprom_rec2nps_addr(ras_core, record, &pa, nps);
|
||||
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;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ras_umc_get_new_records(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *records, u32 num)
|
||||
{
|
||||
|
|
@ -343,12 +432,11 @@ static bool ras_umc_check_retired_record(struct ras_core_context *ras_core,
|
|||
|
||||
if (from_eeprom) {
|
||||
nps = ras_umc->umc_err_data.umc_nps_mode;
|
||||
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_RATELIMITED(ras_core->dev,
|
||||
"Failed to adjust eeprom record, ret:%d", ret);
|
||||
}
|
||||
ret = ras_umc_eeprom_rec2nps_rec(ras_core, record, nps);
|
||||
if (ret)
|
||||
RAS_DEV_WARN_RATELIMITED(ras_core->dev,
|
||||
"Failed to adjust eeprom record, ret:%d", ret);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -805,3 +893,14 @@ int ras_umc_translate_soc_pa_and_bank(struct ras_core_context *ras_core,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t ras_umc_bit_wise_xor(uint32_t val)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
result = result ^ ((val >> i) & 0x1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#define UMC_ECC_NEW_DETECTED_TAG 0x1
|
||||
#define UMC_INV_MEM_PFN (0xFFFFFFFFFFFFFFFF)
|
||||
/* invalid node instance value */
|
||||
#define UMC_INV_AID_NODE 0xffff
|
||||
|
||||
/*
|
||||
* a flag to indicate v2 format channel index stored in eeprom
|
||||
|
|
@ -119,8 +121,6 @@ struct umc_bank_addr {
|
|||
struct ras_umc_ip_func {
|
||||
int (*bank_to_eeprom_record)(struct ras_core_context *ras_core,
|
||||
struct ras_bank_ecc *bank, struct eeprom_umc_record *record);
|
||||
int (*eeprom_record_to_nps_record)(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint32_t nps);
|
||||
int (*eeprom_record_to_nps_pages)(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint32_t nps,
|
||||
uint64_t *pfns, uint32_t num);
|
||||
|
|
@ -130,6 +130,11 @@ struct ras_umc_ip_func {
|
|||
uint64_t soc_pa, struct umc_bank_addr *bank_addr);
|
||||
void (*mca_ipid_parse)(struct ras_core_context *ras_core, uint64_t ipid,
|
||||
uint32_t *did, uint32_t *ch, uint32_t *umc_inst, uint32_t *sid);
|
||||
int (*ma2pa)(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
|
||||
uint32_t nps);
|
||||
uint64_t (*nps_pa_to_row_pa)(struct ras_core_context *ras_core,
|
||||
uint64_t pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok);
|
||||
};
|
||||
|
||||
struct eeprom_store_record {
|
||||
|
|
@ -184,7 +189,7 @@ int ras_umc_sw_init(struct ras_core_context *ras);
|
|||
int ras_umc_sw_fini(struct ras_core_context *ras);
|
||||
int ras_umc_hw_init(struct ras_core_context *ras);
|
||||
int ras_umc_hw_fini(struct ras_core_context *ras);
|
||||
int ras_umc_psp_convert_ma_to_pa(struct ras_core_context *ras_core,
|
||||
int ras_umc_psp_ma2pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *in, struct umc_phy_addr *out,
|
||||
uint32_t nps);
|
||||
int ras_umc_handle_bad_pages(struct ras_core_context *ras_core, void *data);
|
||||
|
|
@ -207,4 +212,8 @@ int ras_umc_translate_soc_pa_and_bank(struct ras_core_context *ras_core,
|
|||
int ras_umc_convert_record_to_nps_pages(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint32_t nps,
|
||||
uint64_t *page_pfn, uint32_t max_pages);
|
||||
uint32_t ras_umc_bit_wise_xor(uint32_t val);
|
||||
int ras_umc_ma2pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
|
||||
uint32_t nps);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -48,17 +48,6 @@ static const uint32_t umc_v12_0_ma2na_mapping[] = {
|
|||
24, 7, 29, 30,
|
||||
};
|
||||
|
||||
static bool umc_v12_0_bit_wise_xor(uint32_t val)
|
||||
{
|
||||
bool result = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
result = result ^ ((val >> i) & 0x1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __get_nps_pa_flip_bits(struct ras_core_context *ras_core,
|
||||
enum umc_memory_partition_mode nps,
|
||||
struct umc_flip_bits *flip_bits)
|
||||
|
|
@ -159,7 +148,7 @@ static void __get_nps_pa_flip_bits(struct ras_core_context *ras_core,
|
|||
}
|
||||
}
|
||||
|
||||
static uint64_t convert_nps_pa_to_row_pa(struct ras_core_context *ras_core,
|
||||
static uint64_t umc_v12_0_nps_pa_to_row_pa(struct ras_core_context *ras_core,
|
||||
uint64_t pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok)
|
||||
{
|
||||
struct umc_flip_bits flip_bits = {0};
|
||||
|
|
@ -193,7 +182,7 @@ static int lookup_bad_pages_in_a_row(struct ras_core_context *ras_core,
|
|||
|
||||
__get_nps_pa_flip_bits(ras_core, nps, &flip_bits);
|
||||
|
||||
row_pa = convert_nps_pa_to_row_pa(ras_core, retired_addr, nps, true);
|
||||
row_pa = umc_v12_0_nps_pa_to_row_pa(ras_core, retired_addr, nps, true);
|
||||
|
||||
err_addr = record->address;
|
||||
/* get column bit 0 and 1 in mca address */
|
||||
|
|
@ -240,7 +229,7 @@ static int lookup_bad_pages_in_a_row(struct ras_core_context *ras_core,
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int umc_v12_convert_ma_to_pa(struct ras_core_context *ras_core,
|
||||
static int umc_v12_0_ma2pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
|
||||
uint32_t nps)
|
||||
{
|
||||
|
|
@ -277,20 +266,20 @@ static int umc_v12_convert_ma_to_pa(struct ras_core_context *ras_core,
|
|||
/* apply bank hash algorithm */
|
||||
bank0 =
|
||||
bank_hash0 ^ (UMC_V12_0_XOR_EN0 &
|
||||
(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR0) ^
|
||||
(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR0))));
|
||||
(ras_umc_bit_wise_xor(col & UMC_V12_0_COL_XOR0) ^
|
||||
(ras_umc_bit_wise_xor(row & UMC_V12_0_ROW_XOR0))));
|
||||
bank1 =
|
||||
bank_hash1 ^ (UMC_V12_0_XOR_EN1 &
|
||||
(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR1) ^
|
||||
(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR1))));
|
||||
(ras_umc_bit_wise_xor(col & UMC_V12_0_COL_XOR1) ^
|
||||
(ras_umc_bit_wise_xor(row & UMC_V12_0_ROW_XOR1))));
|
||||
bank2 =
|
||||
bank_hash2 ^ (UMC_V12_0_XOR_EN2 &
|
||||
(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR2) ^
|
||||
(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR2))));
|
||||
(ras_umc_bit_wise_xor(col & UMC_V12_0_COL_XOR2) ^
|
||||
(ras_umc_bit_wise_xor(row & UMC_V12_0_ROW_XOR2))));
|
||||
bank3 =
|
||||
bank_hash3 ^ (UMC_V12_0_XOR_EN3 &
|
||||
(umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR3) ^
|
||||
(umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR3))));
|
||||
(ras_umc_bit_wise_xor(col & UMC_V12_0_COL_XOR3) ^
|
||||
(ras_umc_bit_wise_xor(row & UMC_V12_0_ROW_XOR3))));
|
||||
|
||||
bank = bank0 | (bank1 << 1) | (bank2 << 2) | (bank3 << 3);
|
||||
err_addr &= ~0x3c0ULL;
|
||||
|
|
@ -360,22 +349,6 @@ static int umc_v12_convert_ma_to_pa(struct ras_core_context *ras_core,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int convert_ma_to_pa(struct ras_core_context *ras_core,
|
||||
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
|
||||
uint32_t nps)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ras_psp_check_supported_cmd(ras_core, RAS_TA_CMD_ID__QUERY_ADDRESS))
|
||||
ret = ras_umc_psp_convert_ma_to_pa(ras_core,
|
||||
addr_in, addr_out, nps);
|
||||
else
|
||||
ret = umc_v12_convert_ma_to_pa(ras_core,
|
||||
addr_in, addr_out, nps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_bank_to_nps_addr(struct ras_core_context *ras_core,
|
||||
struct ras_bank_ecc *bank, struct umc_phy_addr *pa_addr, uint32_t nps)
|
||||
{
|
||||
|
|
@ -392,10 +365,10 @@ static int convert_bank_to_nps_addr(struct ras_core_context *ras_core,
|
|||
addr_in.node_inst = ACA_IPID_2_DIE_ID(bank->ipid);
|
||||
addr_in.socket_id = ACA_IPID_2_SOCKET_ID(bank->ipid);
|
||||
|
||||
ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
|
||||
ret = ras_umc_ma2pa(ras_core, &addr_in, &addr_out, nps);
|
||||
if (!ret) {
|
||||
pa_addr->pa =
|
||||
convert_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false);
|
||||
umc_v12_0_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false);
|
||||
pa_addr->channel_idx = addr_out.channel_idx;
|
||||
pa_addr->bank = addr_out.bank;
|
||||
}
|
||||
|
|
@ -429,68 +402,6 @@ static int umc_v12_0_bank_to_eeprom_record(struct ras_core_context *ras_core,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int convert_eeprom_record_to_nps_addr(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint64_t *pa, uint32_t nps)
|
||||
{
|
||||
struct device_system_info dev_info = {0};
|
||||
struct umc_mca_addr addr_in;
|
||||
struct umc_phy_addr addr_out;
|
||||
int ret;
|
||||
|
||||
memset(&addr_in, 0, sizeof(addr_in));
|
||||
memset(&addr_out, 0, sizeof(addr_out));
|
||||
|
||||
ras_core_get_device_system_info(ras_core, &dev_info);
|
||||
|
||||
addr_in.err_addr = record->address;
|
||||
addr_in.ch_inst = record->mem_channel;
|
||||
addr_in.umc_inst = record->mcumc_id;
|
||||
addr_in.node_inst = UMC_INV_AID_NODE;
|
||||
addr_in.socket_id = dev_info.socket_id;
|
||||
|
||||
ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*pa = convert_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 ch_idx_v2, pa = 0;
|
||||
uint32_t save_nps;
|
||||
int ret = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
/* old eeprom data format, the scope of channel index is
|
||||
* limited to umc instance
|
||||
*/
|
||||
/* TODO */
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
record->cur_nps = nps;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int umc_v12_0_eeprom_record_to_nps_pages(struct ras_core_context *ras_core,
|
||||
struct eeprom_umc_record *record, uint32_t nps,
|
||||
uint64_t *pfns, uint32_t num)
|
||||
|
|
@ -580,10 +491,11 @@ static void umc_v12_0_mca_ipid_parse(struct ras_core_context *ras_core, uint64_t
|
|||
|
||||
const struct ras_umc_ip_func ras_umc_func_v12_0 = {
|
||||
.bank_to_eeprom_record = umc_v12_0_bank_to_eeprom_record,
|
||||
.eeprom_record_to_nps_record = umc_v12_0_eeprom_record_to_nps_record,
|
||||
.eeprom_record_to_nps_pages = umc_v12_0_eeprom_record_to_nps_pages,
|
||||
.bank_to_soc_pa = umc_12_0_bank_to_soc_pa,
|
||||
.soc_pa_to_bank = umc_12_0_soc_pa_to_bank,
|
||||
.mca_ipid_parse = umc_v12_0_mca_ipid_parse,
|
||||
.ma2pa = umc_v12_0_ma2pa,
|
||||
.nps_pa_to_row_pa = umc_v12_0_nps_pa_to_row_pa,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -296,9 +296,6 @@
|
|||
/* C2, C3, C4, R13, four MCA bits are looped in page retirement */
|
||||
#define UMC_V12_0_RETIRE_LOOP_BITS 4
|
||||
|
||||
/* invalid node instance value */
|
||||
#define UMC_INV_AID_NODE 0xffff
|
||||
|
||||
#define UMC_V12_0_AID_NUM_MAX 4
|
||||
#define UMC_V12_0_SOCKET_NUM_MAX 8
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user