From: YiPeng Chai <[email protected]>

Rework fw eeprom handling for new management interface:
- Support new eeprom management interfaces.
- Use ras_mp1 common interfaces to retrieve bad page information
- Keep a local backup to reduce the interaction frequency with MP1.

Signed-off-by: YiPeng Chai <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/ras/core/eeprom_fw.c      | 565 +++++-------------
 drivers/gpu/drm/amd/ras/core/eeprom_fw.h      |  67 +--
 drivers/gpu/drm/amd/ras/core/ras.h            |   1 -
 drivers/gpu/drm/amd/ras/core/ras_eeprom_mgr.c |   5 +
 drivers/gpu/drm/amd/ras/core/ras_umc.c        |   3 +-
 5 files changed, 169 insertions(+), 472 deletions(-)

diff --git a/drivers/gpu/drm/amd/ras/core/eeprom_fw.c 
b/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
index 59e195652e427..f7fb2dd7afe72 100644
--- a/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
+++ b/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
@@ -23,156 +23,18 @@
  */
 
 #include "ras.h"
+#include "ras_mp1.h"
+#include "eeprom_fw.h"
+#define MAX_EEPROM_ERR_RECORD_NUM 1024
 
-#define RAS_SMU_MESSAGE_TIMEOUT_MS 1000 /* 1s */
-
-void ras_fw_init_feature_flags(struct ras_core_context *ras_core)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-       uint64_t flags = 0ULL;
-
-       if (!sys_func || !sys_func->mp1_get_ras_enabled_mask)
-               return;
-
-       if (!sys_func->mp1_get_ras_enabled_mask(ras_core, &flags))
-               ras_core->ras_fw_features = flags;
-}
-
-bool ras_fw_eeprom_supported(struct ras_core_context *ras_core)
-{
-       return !!(ras_core->ras_fw_features & 
RAS_CORE_FW_FEATURE_BIT__RAS_EEPROM);
-}
-
-int ras_fw_get_table_version(struct ras_core_context *ras_core,
-                                    uint32_t *table_version)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-
-       return sys_func->mp1_send_eeprom_msg(ras_core,
-                               RAS_SMU_GetRASTableVersion, 0, table_version);
-}
-
-int ras_fw_get_badpage_count(struct ras_core_context *ras_core,
-                                    uint32_t *count, uint32_t timeout)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-       uint64_t end, now;
-       int ret = 0;
-
-       now = (uint64_t)ktime_to_ms(ktime_get());
-       end = now + timeout;
-
-       do {
-               ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetBadPageCount, 0, count);
-               /* eeprom is not ready */
-               if (ret != -EBUSY)
-                       return ret;
-
-               usleep_range(10000, 15000);
-               now = (uint64_t)ktime_to_ms(ktime_get());
-       } while (now < end);
-
-       RAS_DEV_ERR(ras_core->dev,
-                       "smu get bad page count timeout!\n");
-       return ret;
-}
-
-int ras_fw_get_badpage_mca_addr(struct ras_core_context *ras_core,
-                                       uint16_t index, uint64_t *mca_addr)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-       uint32_t temp_arg, temp_addr_lo, temp_addr_high;
-       int ret;
-
-       temp_arg = index | (1 << 16);
-       ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetBadPageMcaAddr, temp_arg, &temp_addr_lo);
-       if (ret)
-               return ret;
-
-       temp_arg = index | (2 << 16);
-       ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetBadPageMcaAddr, temp_arg, &temp_addr_high);
-
-       if (!ret)
-               *mca_addr = (uint64_t)temp_addr_high << 32 | temp_addr_lo;
-
-       return ret;
-}
-
-int ras_fw_set_timestamp(struct ras_core_context *ras_core,
-                                uint64_t timestamp)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-
-       return sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_SetTimestamp, (uint32_t)timestamp, 0);
-}
-
-int ras_fw_get_timestamp(struct ras_core_context *ras_core,
-                                uint16_t index, uint64_t *timestamp)
+static int fw_eeprom_reset_ras_table(struct ras_core_context *ras_core)
 {
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-       uint32_t temp = 0;
-       int ret;
-
-       ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetTimestamp, index, &temp);
-       if (!ret)
-               *timestamp = temp;
-
-       return ret;
-}
-
-int ras_fw_get_badpage_ipid(struct ras_core_context *ras_core,
-                                   uint16_t index, uint64_t *ipid)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-       uint32_t temp_arg, temp_ipid_lo, temp_ipid_high;
-       int ret;
-
-       temp_arg = index | (1 << 16);
-       ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetBadPageIpid, temp_arg, &temp_ipid_lo);
-       if (ret)
-               return ret;
-
-       temp_arg = index | (2 << 16);
-       ret = sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_GetBadPageIpid, temp_arg, &temp_ipid_high);
-       if (!ret)
-               *ipid = (uint64_t)temp_ipid_high << 32 | temp_ipid_lo;
-
-       return ret;
-}
-
-int ras_fw_erase_ras_table(struct ras_core_context *ras_core,
-                                  uint32_t *result)
-{
-       struct ras_mp1 *mp1 = &ras_core->ras_mp1;
-       const struct ras_mp1_sys_func *sys_func = mp1->sys_func;
-
-       return sys_func->mp1_send_eeprom_msg(ras_core,
-                       RAS_SMU_EraseRasTable, 0, result);
-}
-
-int ras_fw_eeprom_reset_table(struct ras_core_context *ras_core)
-{
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
+       struct fw_eeprom_control *ctl = ras_core->eeprom_mgr.ras_eeprom;
        u32 erase_res = 0;
        int res;
 
-       mutex_lock(&control->ras_tbl_mutex);
-
-       res = ras_fw_erase_ras_table(ras_core, &erase_res);
+       mutex_lock(&ctl->record_lock);
+       res = ras_mp1_reset_ras_table(ras_core, &erase_res);
        if (res || erase_res) {
                RAS_DEV_WARN(ras_core->dev, "RAS EEPROM reset failed, res:%d 
result:%d",
                                                                        res, 
erase_res);
@@ -180,343 +42,220 @@ int ras_fw_eeprom_reset_table(struct ras_core_context 
*ras_core)
                        res = -EIO;
        }
 
-       control->ras_num_recs = 0;
-       control->bad_channel_bitmap = 0;
-       ras_core_event_notify(ras_core, RAS_EVENT_ID__UPDATE_BAD_PAGE_NUM,
-               &control->ras_num_recs);
-       ras_core_event_notify(ras_core, RAS_EVENT_ID__UPDATE_BAD_CHANNEL_BITMAP,
-               &control->bad_channel_bitmap);
-       control->update_channel_flag = false;
+       ctl->record_count = 0;
+       memset(ctl->records, 0,
+               sizeof(*ctl->records) * MAX_EEPROM_ERR_RECORD_NUM);
 
-       mutex_unlock(&control->ras_tbl_mutex);
+       ctl->ras_table_format_version = 0;
+       ctl->eeprom_status = 0;
+       ctl->rma_status = 0;
+       ctl->bad_channel_bitmap = 0;
 
        return res;
 }
 
-bool ras_fw_eeprom_check_safety_watermark(struct ras_core_context *ras_core)
+static int fw_eeprom_sync_data(struct ras_core_context *ras_core,
+               struct fw_eeprom_control *ctl)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       bool ret = false;
-       int bad_page_count;
-
-       if (!control->record_threshold_config)
-               return false;
+       struct eeprom_err_record err_rec = {0};
+       u32 fw_err_rec_num;
+       u32 idx;
+       int ret = 0;
 
-       bad_page_count = ras_umc_get_badpage_count(ras_core);
+       mutex_lock(&ctl->record_lock);
+       ret = ras_mp1_get_record_count(ras_core, &fw_err_rec_num);
+       if (ret)
+               goto out;
+
+       if (!fw_err_rec_num || fw_err_rec_num == ctl->record_count) {
+               goto out;
+       } else if (fw_err_rec_num < ctl->record_count) {
+               RAS_DEV_ERR(ras_core->dev, "EEPROM ECC error count 
mismatch!\n");
+               ret = -EFAULT;
+               goto out;
+       }
 
-       if (bad_page_count > control->record_threshold_count)
-               RAS_DEV_WARN(ras_core->dev, "RAS records:%d exceed 
threshold:%d",
-                       bad_page_count, control->record_threshold_count);
+       for (idx = ctl->record_count;
+                       idx < fw_err_rec_num; idx++, ctl->record_count = idx) {
+               ret = ras_mp1_get_record(ras_core, idx, &err_rec);
+               if (ret)
+                       goto out;
 
-       if ((control->record_threshold_config == WARN_NONSTOP_OVER_THRESHOLD) ||
-               (control->record_threshold_config == NONSTOP_OVER_THRESHOLD)) {
-               RAS_DEV_WARN(ras_core->dev,
-                       "Please consult AMD Service Action Guide (SAG) for 
appropriate service procedures.\n");
-               ret = false;
-       } else {
-               ras_core->is_rma = true;
-               RAS_DEV_WARN(ras_core->dev,
-                       "Please consider adjusting the customized 
threshold.\n");
-               ret = true;
+               memcpy(&ctl->records[idx], &err_rec, sizeof(*ctl->records));
        }
 
+out:
+       mutex_unlock(&ctl->record_lock);
        return ret;
 }
 
-int ras_fw_eeprom_append(struct ras_core_context *ras_core,
-                          struct eeprom_umc_record *record, const u32 num)
+static u32 fw_eeprom_get_record_count(struct ras_core_context *ras_core)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       int threshold_config = control->record_threshold_config;
-       int i, bad_page_count;
-
-       mutex_lock(&control->ras_tbl_mutex);
-
-       for (i = 0; i < num; i++) {
-               /* update bad channel bitmap */
-               if ((record[i].mem_channel < 
BITS_PER_TYPE(control->bad_channel_bitmap)) &&
-                       !(control->bad_channel_bitmap & (1 << 
record[i].mem_channel))) {
-                       control->bad_channel_bitmap |= 1 << 
record[i].mem_channel;
-                       control->update_channel_flag = true;
-               }
-       }
-       control->ras_num_recs += num;
+       struct fw_eeprom_control *ctl;
 
-       bad_page_count = ras_umc_get_badpage_count(ras_core);
+       if (!ras_core->eeprom_mgr.ras_eeprom)
+               return 0;
 
-       if (threshold_config != 0 &&
-               bad_page_count > control->record_threshold_count) {
-               RAS_DEV_WARN(ras_core->dev,
-                       "Saved bad pages %d reaches threshold value %d\n",
-                       bad_page_count, control->record_threshold_count);
+       ctl = ras_core->eeprom_mgr.ras_eeprom;
 
-               if ((threshold_config != WARN_NONSTOP_OVER_THRESHOLD) &&
-                       (threshold_config != NONSTOP_OVER_THRESHOLD))
-                       ras_core->is_rma = true;
+       if (!ras_core_gpu_in_reset(ras_core))
+               fw_eeprom_sync_data(ras_core, ctl);
 
-               /* ignore the -ENOTSUPP return value */
-               ras_core_event_notify(ras_core, RAS_EVENT_ID__DEVICE_RMA, NULL);
-       }
-
-       mutex_unlock(&control->ras_tbl_mutex);
-       return 0;
+       return ctl->record_count;
 }
 
-int ras_fw_eeprom_read_idx(struct ras_core_context *ras_core,
-                        struct eeprom_umc_record *record_umc,
-                        struct ras_bank_ecc *ras_ecc,
-                        u32 rec_idx, const u32 num)
+static int fw_eeprom_get_record(struct ras_core_context *ras_core,
+               u32 idx, struct eeprom_umc_record *rec)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       int i, ret, end_idx;
-       u64 mca, ipid, ts;
-       u32 cu, mem_channel, mcumc_id;
-
-       if (!ras_core->ras_umc.ip_func ||
-           !ras_core->ras_umc.ip_func->mca_ipid_parse)
-               return -EOPNOTSUPP;
+       struct fw_eeprom_control *ctl;
+       struct ras_bank_ecc bank = {0};
 
-       mutex_lock(&control->ras_tbl_mutex);
-
-       end_idx = rec_idx + num;
-       for (i = rec_idx; i < end_idx; i++) {
-               ret = ras_fw_get_badpage_mca_addr(ras_core, i, &mca);
-               if (ret)
-                       goto out;
-
-               ret = ras_fw_get_badpage_ipid(ras_core, i, &ipid);
-               if (ret)
-                       goto out;
+       if (!ras_core->eeprom_mgr.ras_eeprom)
+               return -EINVAL;
 
-               ret = ras_fw_get_timestamp(ras_core, i, &ts);
-               if (ret)
-                       goto out;
+       ctl = ras_core->eeprom_mgr.ras_eeprom;
 
-               if (record_umc) {
-                       record_umc[i - rec_idx].address = mca;
-                       /* retired_page (pa) is unused now */
-                       record_umc[i - rec_idx].retired_row_pfn = 0x1ULL;
-                       record_umc[i - rec_idx].ts = ts;
-                       record_umc[i - rec_idx].err_type = 
RAS_EEPROM_ERR_NON_RECOVERABLE;
-
-                       ras_core->ras_umc.ip_func->mca_ipid_parse(ras_core, 
ipid,
-                               &cu, &mem_channel, &mcumc_id, NULL);
-                       record_umc[i - rec_idx].cu = (u8)cu;
-                       record_umc[i - rec_idx].mem_channel = (u8)mem_channel;
-                       record_umc[i - rec_idx].mcumc_id = (u8)mcumc_id;
-
-                       /* update bad channel bitmap */
-                       if ((record_umc[i - rec_idx].mem_channel < 
BITS_PER_TYPE(control->bad_channel_bitmap)) &&
-                               !(control->bad_channel_bitmap & (1 << 
record_umc[i - rec_idx].mem_channel))) {
-                               control->bad_channel_bitmap |= 1 << 
record_umc[i - rec_idx].mem_channel;
-                               control->update_channel_flag = true;
-                       }
-               }
-
-               if (ras_ecc) {
-                       ras_ecc[i - rec_idx].addr = mca;
-                       ras_ecc[i - rec_idx].ipid = ipid;
-                       ras_ecc[i - rec_idx].ts = ts;
-               }
+       if (!rec || idx >= ctl->record_count)
+               return -EINVAL;
 
-       }
+       bank.timestamp = ctl->records[idx].timestamp;
+       bank.status = 0;
+       bank.ipid = ctl->records[idx].ipid;
+       bank.addr = ctl->records[idx].mca_addr;
+       bank.nps = ras_core_get_curr_nps_mode(ras_core);
 
-out:
-       mutex_unlock(&control->ras_tbl_mutex);
-       return ret;
+       return ras_umc_bank_to_umc_record(ras_core, &bank, rec);
 }
 
-uint32_t ras_fw_eeprom_get_record_count(struct ras_core_context *ras_core)
+static int fw_eeprom_sw_init(struct ras_core_context *ras_core,
+                       struct ras_eeprom_param *param)
 {
-       if (!ras_core)
-               return 0;
+       struct ras_eeprom_mgr *mgr = &ras_core->eeprom_mgr;
+       struct fw_eeprom_control *ctl;
+       int ret = 0;
 
-       return ras_core->ras_fw_eeprom.ras_num_recs;
-}
+       if (!param)
+               return -EINVAL;
 
-int ras_fw_eeprom_update_record(struct ras_core_context *ras_core,
-                               struct ras_bank_ecc *ras_ecc)
-{
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       int ret, retry = 20;
-       u32 recs_num_new = control->ras_num_recs;
-
-       do {
-               /* 1000ms timeout is long enough, smu_get_badpage_count won't
-                * return -EBUSY before timeout.
-                */
-               ret = ras_fw_get_badpage_count(ras_core,
-                       &recs_num_new, RAS_SMU_MESSAGE_TIMEOUT_MS);
-               if (!ret &&
-                   (recs_num_new == control->ras_num_recs)) {
-                       /* record number update in PMFW needs some time,
-                        * smu_get_badpage_count may return immediately without
-                        * count update, sleep for a while and retry again.
-                        */
-                       msleep(50);
-                       retry--;
-               } else {
-                       break;
-               }
-       } while (retry);
+       ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
+       if (!ctl)
+               return -ENOMEM;
 
-       if (ret)
-               return ret;
+       mgr->ras_eeprom = ctl;
+       memset(ctl, 0, sizeof(*ctl));
 
-       if (recs_num_new > control->ras_num_recs)
-               ret = ras_fw_eeprom_read_idx(ras_core, 0,
-                                       ras_ecc, control->ras_num_recs, 1);
-       else
-               ret = -EINVAL;
+       ctl->eeprom_ip_version = param->eeprom_ip_version;
+       ctl->records = kzalloc(sizeof(*ctl->records) * 
MAX_EEPROM_ERR_RECORD_NUM, GFP_KERNEL);
+       if (!ctl->records) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
+       ctl->max_record_count = MAX_EEPROM_ERR_RECORD_NUM;
+       mutex_init(&ctl->record_lock);
+
+       return 0;
+
+out:
+       kfree(ctl->records);
        return ret;
 }
 
-static int __check_ras_fw_table_status(struct ras_core_context *ras_core)
+static int fw_eeprom_sw_fini(struct ras_core_context *ras_core)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       uint64_t local_time;
-       int res;
-
-       mutex_init(&control->ras_tbl_mutex);
-
-       res = ras_fw_get_table_version(ras_core, &(control->version));
-       if (res)
-               return res;
-
-       res = ras_fw_get_badpage_count(ras_core, &(control->ras_num_recs), 100);
-       if (res)
-               return res;
+       struct fw_eeprom_control *ctl;
 
-       local_time = (uint64_t)ktime_get_real_seconds();
-       res = ras_fw_set_timestamp(ras_core, local_time);
-       if (res)
-               return res;
+       if (!ras_core->eeprom_mgr.ras_eeprom)
+               return -EINVAL;
 
-       control->ras_max_record_count = 4000;
+       ctl = ras_core->eeprom_mgr.ras_eeprom;
 
+       kfree(ctl->records);
+       mutex_destroy(&ctl->record_lock);
 
-       if (control->ras_num_recs > control->ras_max_record_count) {
-               RAS_DEV_ERR(ras_core->dev,
-                       "RAS header invalid, records in header: %u max allowed 
:%u",
-                       control->ras_num_recs, control->ras_max_record_count);
-               return -EINVAL;
-       }
+       kfree(ctl);
+       ras_core->eeprom_mgr.ras_eeprom = NULL;
 
        return 0;
 }
 
-int ras_fw_eeprom_hw_init(struct ras_core_context *ras_core)
+static int fw_eeprom_hw_init(struct ras_core_context *ras_core,
+                       struct ras_eeprom_param *param)
 {
-       struct ras_fw_eeprom_control *control;
-       struct ras_eeprom_config *eeprom_cfg;
-       struct ras_mp1 *mp1;
-       const struct ras_mp1_sys_func *sys_func;
-
-       if (!ras_core)
-               return -EINVAL;
-
-       mp1 = &ras_core->ras_mp1;
-       sys_func = mp1->sys_func;
+       struct fw_eeprom_control *ctl;
 
-       if (!sys_func || !sys_func->mp1_send_eeprom_msg)
+       if (!ras_core->eeprom_mgr.ras_eeprom)
                return -EINVAL;
 
-       ras_core->is_rma = false;
-
-       control = &ras_core->ras_fw_eeprom;
-
-       memset(control, 0, sizeof(*control));
+       ctl = ras_core->eeprom_mgr.ras_eeprom;
 
-       eeprom_cfg = &ras_core->config->eeprom_cfg;
-       control->record_threshold_config =
-               eeprom_cfg->eeprom_record_threshold_config;
+       ras_mp1_get_table_version(ras_core, &ctl->ras_table_format_version);
 
-       control->record_threshold_count = 4000;
-       if (eeprom_cfg->eeprom_record_threshold_count <
-               control->record_threshold_count)
-               control->record_threshold_count =
-                       eeprom_cfg->eeprom_record_threshold_count;
-
-       control->update_channel_flag = false;
-
-       return __check_ras_fw_table_status(ras_core);
+       return 0;
 }
 
-int ras_fw_eeprom_hw_fini(struct ras_core_context *ras_core)
+static int fw_eeprom_hw_fini(struct ras_core_context *ras_core)
 {
-       struct ras_fw_eeprom_control *control;
-
-       if (!ras_core)
-               return -EINVAL;
-
-       control = &ras_core->ras_fw_eeprom;
-       mutex_destroy(&control->ras_tbl_mutex);
-
        return 0;
 }
 
-int ras_fw_eeprom_check_storage_status(struct ras_core_context *ras_core)
+static int fw_eeprom_get_records(struct ras_core_context *ras_core, u32 start,
+               struct eeprom_umc_record *record, u32 num)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
-       int bad_page_count;
-
-       bad_page_count = ras_umc_get_badpage_count(ras_core);
-
-       if ((control->record_threshold_count < bad_page_count) &&
-           (control->record_threshold_config != 0)) {
-               RAS_DEV_ERR(ras_core->dev, "RAS records:%d exceed threshold:%d",
-                               bad_page_count, 
control->record_threshold_count);
-               if ((control->record_threshold_config == 
WARN_NONSTOP_OVER_THRESHOLD) ||
-                       (control->record_threshold_config == 
NONSTOP_OVER_THRESHOLD)) {
-                       RAS_DEV_WARN(ras_core->dev,
-                       "Please consult AMD Service Action Guide (SAG) for 
appropriate service procedures\n");
-               } else {
-                       ras_core->is_rma = true;
-                       RAS_DEV_ERR(ras_core->dev,
-                       "User defined threshold is set, runtime service will be 
halt when threshold is reached\n");
-               }
-               return 0;
-       }
+       struct fw_eeprom_control *ctl = ras_core->eeprom_mgr.ras_eeprom;
+       int i, ret = 0;
 
-       RAS_DEV_INFO(ras_core->dev,
-                       "Found existing EEPROM table with %d records\n",
-                       bad_page_count);
-       /* Warn if we are at 90% of the threshold or above
-        */
-       if (10 * bad_page_count >= 9 * control->record_threshold_count)
-               RAS_DEV_WARN(ras_core->dev,
-                       "RAS records:%u exceeds 90%% of threshold:%d\n",
-                       bad_page_count,
-                       control->record_threshold_count);
+       mutex_lock(&ctl->record_lock);
+       for (i = 0; i < num; i++) {
+               ret = fw_eeprom_get_record(ras_core, start + i, &record[i]);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&ctl->record_lock);
 
-       return 0;
+       return ret;
 }
 
-enum ras_gpu_health_status
-       ras_fw_eeprom_check_gpu_status(struct ras_core_context *ras_core)
+static int fw_eeprom_get_eeprom_info(struct ras_core_context *ras_core,
+               struct ras_eeprom_info *eeprom_info, bool fast_mode)
 {
-       struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
+       struct fw_eeprom_control *ctl = ras_core->eeprom_mgr.ras_eeprom;
+
+       if (!eeprom_info)
+               return -EINVAL;
 
-       if (!control->record_threshold_config)
-               return RAS_GPU_HEALTH_NONE;
+       eeprom_info->record_count = ctl->record_count;
+       eeprom_info->max_record_count = ctl->max_record_count;
+       eeprom_info->bad_channel_bitmap = ctl->bad_channel_bitmap;
 
-       if (ras_core->is_rma)
-               return RAS_GPU_RETIRED__ECC_REACH_THRESHOLD;
+       if (!fast_mode) {
+               if (!ctl->ras_table_format_version)
+                       ras_mp1_get_table_version(ras_core,
+                               &ctl->ras_table_format_version);
 
-       return RAS_GPU_HEALTH_USABLE;
-}
+               eeprom_info->rma_status = ras_mp1_rma_detected(ras_core);
+               ctl->rma_status = eeprom_info->rma_status;
+       } else {
+               eeprom_info->rma_status = ctl->rma_status;
+       }
 
-void ras_fw_eeprom_sync_info(struct ras_core_context *ras_core)
-{
-       struct ras_fw_eeprom_control *control;
+       eeprom_info->record_format_version = ctl->ras_table_format_version;
 
-       if (!ras_core)
-               return;
+       if (eeprom_info->rma_status)
+               eeprom_info->eeprom_status = RAS_EEPROM_LOCKED;
+       else
+               eeprom_info->eeprom_status = RAS_EEPROM_OK;
 
-       control = &ras_core->ras_fw_eeprom;
-       ras_core_event_notify(ras_core, RAS_EVENT_ID__UPDATE_BAD_PAGE_NUM,
-               &control->ras_num_recs);
-       ras_core_event_notify(ras_core, RAS_EVENT_ID__UPDATE_BAD_CHANNEL_BITMAP,
-               &control->bad_channel_bitmap);
+       return 0;
 }
+
+struct ras_eeprom_ops ras_fw_eeprom_ops = {
+       .sw_init = fw_eeprom_sw_init,
+       .sw_fini = fw_eeprom_sw_fini,
+       .hw_init = fw_eeprom_hw_init,
+       .hw_fini = fw_eeprom_hw_fini,
+       .reset_table = fw_eeprom_reset_ras_table,
+       .get_records = fw_eeprom_get_records,
+       .get_record_count = fw_eeprom_get_record_count,
+       .get_eeprom_info = fw_eeprom_get_eeprom_info,
+};
diff --git a/drivers/gpu/drm/amd/ras/core/eeprom_fw.h 
b/drivers/gpu/drm/amd/ras/core/eeprom_fw.h
index 803d3ccdaddbd..8fc8773732ece 100644
--- a/drivers/gpu/drm/amd/ras/core/eeprom_fw.h
+++ b/drivers/gpu/drm/amd/ras/core/eeprom_fw.h
@@ -23,65 +23,18 @@
  */
 #ifndef __EEPROM_FW_H__
 #define __EEPROM_FW_H__
+struct fw_eeprom_control {
+       u32 eeprom_ip_version;
+       struct mutex record_lock;
+       struct eeprom_err_record *records;
+       u32 record_count;
 
-struct ras_fw_eeprom_control {
-       uint32_t version;
-       /* record threshold */
-       int record_threshold_config;
-       uint32_t record_threshold_count;
-       bool update_channel_flag;
-
-       /* Number of records in the table.
-        */
-       u32 ras_num_recs;
-
-       /* Maximum possible number of records
-        * we could store, i.e. the maximum capacity
-        * of the table.
-        */
-       u32 ras_max_record_count;
-
-       /* Protect table access via this mutex.
-        */
-       struct mutex ras_tbl_mutex;
-
-       /* Record channel info which occurred bad pages
-        */
+       u32 ras_table_format_version;
+       u32 eeprom_status;
+       u32 rma_status;
+       u32 max_record_count;
        u32 bad_channel_bitmap;
 };
 
-void ras_fw_init_feature_flags(struct ras_core_context *ras_core);
-bool ras_fw_eeprom_supported(struct ras_core_context *ras_core);
-int ras_fw_get_table_version(struct ras_core_context *ras_core,
-                                    uint32_t *table_version);
-int ras_fw_get_badpage_count(struct ras_core_context *ras_core,
-                                    uint32_t *count, uint32_t timeout);
-int ras_fw_get_badpage_mca_addr(struct ras_core_context *ras_core,
-                                       uint16_t index, uint64_t *mca_addr);
-int ras_fw_set_timestamp(struct ras_core_context *ras_core,
-                                uint64_t timestamp);
-int ras_fw_get_timestamp(struct ras_core_context *ras_core,
-                                uint16_t index, uint64_t *timestamp);
-int ras_fw_get_badpage_ipid(struct ras_core_context *ras_core,
-                                   uint16_t index, uint64_t *ipid);
-int ras_fw_erase_ras_table(struct ras_core_context *ras_core,
-                                  uint32_t *result);
-int ras_fw_eeprom_reset_table(struct ras_core_context *ras_core);
-bool ras_fw_eeprom_check_safety_watermark(struct ras_core_context *ras_core);
-int ras_fw_eeprom_append(struct ras_core_context *ras_core,
-                          struct eeprom_umc_record *record, const u32 num);
-int ras_fw_eeprom_read_idx(struct ras_core_context *ras_core,
-                        struct eeprom_umc_record *record_umc,
-                        struct ras_bank_ecc *ras_ecc,
-                        u32 rec_idx, const u32 num);
-uint32_t ras_fw_eeprom_get_record_count(struct ras_core_context *ras_core);
-int ras_fw_eeprom_update_record(struct ras_core_context *ras_core,
-                               struct ras_bank_ecc *ras_ecc);
-int ras_fw_eeprom_hw_init(struct ras_core_context *ras_core);
-int ras_fw_eeprom_hw_fini(struct ras_core_context *ras_core);
-int ras_fw_eeprom_check_storage_status(struct ras_core_context *ras_core);
-enum ras_gpu_health_status
-       ras_fw_eeprom_check_gpu_status(struct ras_core_context *ras_core);
-void ras_fw_eeprom_sync_info(struct ras_core_context *ras_core);
-
+extern struct ras_eeprom_ops ras_fw_eeprom_ops;
 #endif
diff --git a/drivers/gpu/drm/amd/ras/core/ras.h 
b/drivers/gpu/drm/amd/ras/core/ras.h
index 9c87037454d5c..a08f83ed05857 100644
--- a/drivers/gpu/drm/amd/ras/core/ras.h
+++ b/drivers/gpu/drm/amd/ras/core/ras.h
@@ -385,7 +385,6 @@ struct ras_core_context {
        bool ras_eeprom_supported;
        struct ras_eeprom_control ras_eeprom;
        struct ras_eeprom_mgr eeprom_mgr;
-       struct ras_fw_eeprom_control ras_fw_eeprom;
 
        struct ras_psp ras_psp;
        struct ras_umc ras_umc;
diff --git a/drivers/gpu/drm/amd/ras/core/ras_eeprom_mgr.c 
b/drivers/gpu/drm/amd/ras/core/ras_eeprom_mgr.c
index d56e065ccfc74..1781d037ef13d 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_eeprom_mgr.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_eeprom_mgr.c
@@ -25,6 +25,7 @@
 #include "ras_eeprom_mgr.h"
 #include "ras.h"
 #include "eeprom.h"
+#include "eeprom_fw.h"
 
 static bool __ras_eeprom_disabled(struct ras_core_context *ras_core)
 {
@@ -42,6 +43,10 @@ static const struct ras_eeprom_ops 
*ras_eeprom_mgr_get_ip_func(
        case IP_VERSION(13, 0, 12):
                mgr->eeprom_early_init_service_supported = false;
                return &ras_drv_eeprom_ops;
+       case IP_VERSION(15, 0, 8):
+               mgr->eeprom_early_init_service_supported = true;
+               mgr->fw_record_enabled = true;
+               return &ras_fw_eeprom_ops;
        default:
                RAS_DEV_ERR(ras_core->dev,
                        "EEPROM(MP1) ip version(0x%x) is not supported!\n", 
ip_version);
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c 
b/drivers/gpu/drm/amd/ras/core/ras_umc.c
index 1be677ca316e1..2ff6c9a7e5c17 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_umc.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c
@@ -435,7 +435,8 @@ static int ras_umc_eeprom_rec2nps_rec(struct 
ras_core_context *ras_core,
        record->cur_nps = nps;
 
        if (save_nps || ch_idx_v2) {
-               if ((nps == save_nps) && !ras_fw_eeprom_supported(ras_core)) {
+               if ((nps == save_nps) &&
+                   !ras_eeprom_mgr_fw_record_enabled(ras_core)) {
                        record->cur_nps_retired_row_pfn =
                                EEPROM_RECORD_UMC_ADDR_PFN(record);
                } else {
-- 
2.55.0

Reply via email to