[PATCH 077/109] drm/amd/ras: add management interface to support psp bad page address translation
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> Add management interface to support psp bad page address translation. Signed-off-by: YiPeng Chai <[email protected]> Reviewed-by: Tao Zhou <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/ras/core/eeprom.h | 4 +++ drivers/gpu/drm/amd/ras/core/ras.h | 2 ++ drivers/gpu/drm/amd/ras/core/ras_psp.c | 14 ++++++++++ drivers/gpu/drm/amd/ras/core/ras_psp.h | 19 ++++++++++++++ drivers/gpu/drm/amd/ras/core/ras_umc.c | 27 ++++++++++++++++++-- drivers/gpu/drm/amd/ras/core/ras_umc.h | 8 +++++- drivers/gpu/drm/amd/ras/core/ras_umc_v15_0.c | 21 +++++++++++---- 7 files changed, 87 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/eeprom.h b/drivers/gpu/drm/amd/ras/core/eeprom.h index f4dac13d70056..ae22bb3f83187 100644 --- a/drivers/gpu/drm/amd/ras/core/eeprom.h +++ b/drivers/gpu/drm/amd/ras/core/eeprom.h @@ -163,6 +163,10 @@ struct eeprom_umc_record { /* The following variables will not be saved to eeprom. */ uint64_t cur_nps_retired_row_pfn; + /* Combined PA flip bit mask across all bad pages in a row; + * used with cur_nps_retired_row_pfn to derive all bad page addresses + */ + uint64_t cur_nps_pa_flip_mask; uint32_t cur_nps_bank; uint32_t cur_nps; uint64_t ipid; diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index 168766d449ce7..a2f0491e4062b 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -273,6 +273,8 @@ struct ras_psp_sys_func { struct ras_psp_sys_status *status); int (*get_ras_param)(struct ras_core_context *ras_core, struct ras_param *param); + int (*psp_translate_addr)(struct ras_core_context *ras_core, + struct ras_psp_addr_trans_in *in, struct ras_psp_addr_trans_out *out); }; struct ras_sys_func { diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.c b/drivers/gpu/drm/amd/ras/core/ras_psp.c index 06668332256c2..102dffe9d4989 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp.c +++ b/drivers/gpu/drm/amd/ras/core/ras_psp.c @@ -985,3 +985,17 @@ uint64_t ras_psp_get_hw_ras_caps(struct ras_core_context *ras_core) return psp->ras_hw_caps.features.block_mask; } + +int ras_psp_translate_addr(struct ras_core_context *ras_core, + struct ras_psp_addr_trans_in *in, struct ras_psp_addr_trans_out *out) +{ + struct ras_psp *psp = &ras_core->ras_psp; + + if (!in || !out) + return -EINVAL; + + if (!psp->sys_func || !psp->sys_func->psp_translate_addr) + return -EOPNOTSUPP; + + return psp->sys_func->psp_translate_addr(ras_core, in, out); +} diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.h b/drivers/gpu/drm/amd/ras/core/ras_psp.h index 5e668730cf176..041d46eee3f43 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp.h +++ b/drivers/gpu/drm/amd/ras/core/ras_psp.h @@ -34,6 +34,23 @@ struct ras_ta_query_address_input; struct ras_ta_query_address_output; enum ras_ta_cmd_id; +struct ras_psp_addr_trans_in { + uint64_t mca_addr; + uint64_t ipid; + uint32_t nps; +}; + +struct ras_psp_addr_trans_out { + uint32_t channel_id; + uint8_t socket_id; + uint8_t mem_die_id; + uint8_t dram_entity_id; + uint8_t umc_inst_id; + uint64_t row_pa; + /* Bitmask of flipping bits across all bad page PAs in a row */ + uint64_t pa_flip_mask; +}; + struct ras_ta_image_header { uint32_t reserved1[24]; uint32_t image_version; /* [0x60] Off Chip Firmware Version */ @@ -191,4 +208,6 @@ int ras_psp_get_block_ta_id(struct ras_core_context *ras_core, bool ras_psp_poison_supported(struct ras_core_context *ras_core); bool ras_psp_flex_mca_enabled(struct ras_core_context *ras_core); uint64_t ras_psp_get_hw_ras_caps(struct ras_core_context *ras_core); +int ras_psp_translate_addr(struct ras_core_context *ras_core, + struct ras_psp_addr_trans_in *in, struct ras_psp_addr_trans_out *out); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c b/drivers/gpu/drm/amd/ras/core/ras_umc.c index d78b111b87852..cef5770a75a60 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc.c +++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c @@ -85,7 +85,7 @@ static const struct ras_umc_ip_func *ras_umc_get_ip_func( return NULL; } -int ras_umc_psp_ma2pa(struct ras_core_context *ras_core, +int ras_umc_ras_ta_translate_addr(struct ras_core_context *ras_core, struct umc_mca_addr *in, struct umc_phy_addr *out, uint32_t nps) { @@ -124,6 +124,28 @@ int ras_umc_psp_ma2pa(struct ras_core_context *ras_core, return 0; } +int ras_umc_psp_translate_addr(struct ras_core_context *ras_core, + struct umc_mca_addr *in, struct umc_phy_addr *out, + uint32_t nps) +{ + struct ras_psp_addr_trans_in psp_in = {0}; + struct ras_psp_addr_trans_out psp_out = {0}; + int ret; + + psp_in.mca_addr = in->mca_addr; + psp_in.ipid = in->ipid; + psp_in.nps = nps; + + ret = ras_psp_translate_addr(ras_core, &psp_in, &psp_out); + if (ret) + return ret; + + out->pa = psp_out.row_pa; + out->pa_flip_mask = psp_out.pa_flip_mask; + + return 0; +} + static int ras_umc_log_ecc(struct ras_core_context *ras_core, unsigned long idx, void *data) { @@ -302,7 +324,7 @@ int ras_umc_ma2pa(struct ras_core_context *ras_core, 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); + ret = ras_umc_ras_ta_translate_addr(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); @@ -874,6 +896,7 @@ int ras_umc_fill_eeprom_record(struct ras_core_context *ras_core, err_rec->mem_channel = cur_nps_addr->channel_idx; err_rec->mcumc_id = umc_inst; err_rec->cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(cur_nps_addr->pa); + err_rec->cur_nps_pa_flip_mask = cur_nps_addr->pa_flip_mask; err_rec->cur_nps_bank = cur_nps_addr->bank; err_rec->cur_nps = cur_nps; return 0; diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.h b/drivers/gpu/drm/amd/ras/core/ras_umc.h index 725f74740ead9..a64b5106d0051 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc.h +++ b/drivers/gpu/drm/amd/ras/core/ras_umc.h @@ -104,10 +104,13 @@ struct umc_mca_addr { uint32_t umc_inst; uint32_t node_inst; uint32_t socket_id; + uint64_t mca_addr; + uint64_t ipid; }; struct umc_phy_addr { uint64_t pa; + uint64_t pa_flip_mask; uint32_t bank; uint32_t channel_idx; }; @@ -197,7 +200,10 @@ 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_ma2pa(struct ras_core_context *ras_core, +int ras_umc_ras_ta_translate_addr(struct ras_core_context *ras_core, + struct umc_mca_addr *in, struct umc_phy_addr *out, + uint32_t nps); +int ras_umc_psp_translate_addr(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); diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc_v15_0.c b/drivers/gpu/drm/amd/ras/core/ras_umc_v15_0.c index 0f3182b14dae9..39e95a5515f83 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc_v15_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_umc_v15_0.c @@ -34,15 +34,18 @@ 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, - uint64_t pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok) + struct umc_phy_addr *pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok) { struct umc_flip_bits flip_bits = {0}; uint64_t row_pa; int i; + if (pa->pa_flip_mask) + return zero_pfn_ok ? (pa->pa & ~pa->pa_flip_mask) : pa->pa; + __get_nps_pa_flip_bits(ras_core, nps, &flip_bits); - row_pa = pa; + row_pa = pa->pa; /* clear loop bits in soc physical address */ for (i = 0; i < flip_bits.bit_num; i++) row_pa &= ~BIT_ULL(flip_bits.flip_bits_in_pa[i]); @@ -75,8 +78,13 @@ static int convert_ma_to_pa(struct ras_core_context *ras_core, { int ret; + ret = ras_umc_psp_translate_addr(ras_core, + addr_in, addr_out, nps); + if (ret != -EOPNOTSUPP) + return ret; + if (ras_psp_check_supported_cmd(ras_core, RAS_TA_CMD_ID__QUERY_ADDRESS)) - ret = ras_umc_psp_ma2pa(ras_core, + ret = ras_umc_ras_ta_translate_addr(ras_core, addr_in, addr_out, nps); else ret = umc_v15_convert_ma_to_pa(ras_core, @@ -100,11 +108,14 @@ static int convert_bank_to_nps_addr(struct ras_core_context *ras_core, addr_in.umc_inst = ACA_IPID_2_UMC_INST(bank->ipid); addr_in.node_inst = ACA_IPID_2_DIE_ID(bank->ipid); addr_in.socket_id = ACA_IPID_2_SOCKET_ID(bank->ipid); + addr_in.mca_addr = bank->addr; + addr_in.ipid = bank->ipid; ret = convert_ma_to_pa(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); + convert_nps_pa_to_row_pa(ras_core, &addr_out, nps, false); + pa_addr->pa_flip_mask = addr_out.pa_flip_mask; pa_addr->channel_idx = addr_out.channel_idx; pa_addr->bank = addr_out.bank; } @@ -164,7 +175,7 @@ static int convert_eeprom_record_to_nps_addr(struct ras_core_context *ras_core, if (ret) return ret; - *pa = convert_nps_pa_to_row_pa(ras_core, addr_out.pa, nps, false); + *pa = convert_nps_pa_to_row_pa(ras_core, &addr_out, nps, false); return 0; } -- 2.55.0