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

Reply via email to