[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.