From: YiPeng Chai <[email protected]>

Unify UMC record logging paths for runtime and preload.

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/ras_umc.c | 190 ++++++++++---------------
 drivers/gpu/drm/amd/ras/core/ras_umc.h |   5 +-
 2 files changed, 76 insertions(+), 119 deletions(-)

diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c 
b/drivers/gpu/drm/amd/ras/core/ras_umc.c
index 2ff6c9a7e5c17..9cf1515dfd02e 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_umc.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c
@@ -130,8 +130,6 @@ static int ras_umc_log_ecc(struct ras_core_context 
*ras_core,
 
        mutex_lock(&ras_umc->tree_lock);
        ret = radix_tree_insert(&ras_umc->root, idx, data);
-       if (!ret)
-               radix_tree_tag_set(&ras_umc->root, idx, 
UMC_ECC_NEW_DETECTED_TAG);
        mutex_unlock(&ras_umc->tree_lock);
 
        return ret;
@@ -269,39 +267,24 @@ int ras_umc_log_pending_bad_bank(struct ras_core_context 
*ras_core)
 int ras_umc_log_bad_bank(struct ras_core_context *ras_core, struct 
ras_bank_ecc *bank)
 {
        struct ras_umc *ras_umc = &ras_core->ras_umc;
-       struct eeprom_umc_record umc_rec;
-       struct eeprom_umc_record *err_rec;
+       struct eeprom_umc_record umc_rec = {0};
+       uint32_t c = 0;
        int ret;
 
-       memset(&umc_rec, 0, sizeof(umc_rec));
-
        mutex_lock(&ras_umc->bank_log_lock);
-       ret = ras_umc->ip_func->bank_to_eeprom_record(ras_core, bank, &umc_rec);
+       ret = ras_umc_bank_to_umc_record(ras_core, bank, &umc_rec);
        if (ret)
                goto out;
 
-       err_rec = kzalloc_obj(*err_rec);
-       if (!err_rec) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memcpy(err_rec, &umc_rec, sizeof(umc_rec));
-       ret = ras_umc_log_ecc(ras_core, err_rec->cur_nps_retired_row_pfn, 
err_rec);
+       ret = ras_umc_add_bad_pages(ras_core, &umc_rec, 1, &c);
        if (ret) {
-               if (ret == -EEXIST) {
-                       RAS_DEV_INFO(ras_core->dev, "The bad pages have been 
logged before.\n");
-                       ret = 0;
-               }
-
-               kfree(err_rec);
+               RAS_DEV_ERR(ras_core->dev, "Failed to log bad bank! ret:%x\n", 
ret);
                goto out;
        }
 
-       ras_umc_reserve_eeprom_record(ras_core, err_rec);
-
-       ret = ras_core_event_notify(ras_core,
-                       RAS_EVENT_ID__BAD_PAGE_DETECTED, NULL);
+       if (c)
+               ret = ras_core_event_notify(ras_core,
+                               RAS_EVENT_ID__BAD_PAGE_DETECTED, NULL);
 
 out:
        mutex_unlock(&ras_umc->bank_log_lock);
@@ -468,59 +451,52 @@ static int ras_umc_eeprom_rec2nps_rec(struct 
ras_core_context *ras_core,
        return ret;
 }
 
-static int ras_umc_get_new_records(struct ras_core_context *ras_core,
-                       struct eeprom_umc_record *records, u32 num)
+static bool ras_umc_check_logged_record(struct ras_core_context *ras_core,
+                       struct eeprom_umc_record *record)
 {
        struct ras_umc *ras_umc = &ras_core->ras_umc;
-       struct eeprom_umc_record *entries[MAX_ECC_NUM_PER_RETIREMENT];
-       u32 entry_num = num < MAX_ECC_NUM_PER_RETIREMENT ? num : 
MAX_ECC_NUM_PER_RETIREMENT;
-       int count = 0;
-       int new_detected, i;
+       void *res = NULL;
 
        mutex_lock(&ras_umc->tree_lock);
-       new_detected = radix_tree_gang_lookup_tag(&ras_umc->root, (void 
**)entries,
-                       0, entry_num, UMC_ECC_NEW_DETECTED_TAG);
-       for (i = 0; i < new_detected; i++) {
-               if (!entries[i])
-                       continue;
-
-               memcpy(&records[i], entries[i], sizeof(struct 
eeprom_umc_record));
-               count++;
-               radix_tree_tag_clear(&ras_umc->root,
-                               entries[i]->cur_nps_retired_row_pfn, 
UMC_ECC_NEW_DETECTED_TAG);
-       }
+       res = radix_tree_lookup(&ras_umc->root, 
record->cur_nps_retired_row_pfn);
        mutex_unlock(&ras_umc->tree_lock);
 
-       return count;
+       return res ? true : false;
 }
 
 static bool ras_umc_check_retired_record(struct ras_core_context *ras_core,
-                               struct eeprom_umc_record *record, bool 
from_eeprom)
+                               struct eeprom_umc_record *record)
 {
-       struct ras_umc *ras_umc = &ras_core->ras_umc;
-       struct eeprom_store_record *data = &ras_umc->umc_err_data.rom_data;
        uint32_t nps = 0;
-       int i, ret;
-
-       if (from_eeprom) {
-               nps = ras_core_get_curr_nps_mode(ras_core);
-               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);
+       int ret;
 
-               return false;
+       nps = ras_core_get_curr_nps_mode(ras_core);
+       ret = ras_umc_eeprom_rec2nps_rec(ras_core, record, nps);
+       if (ret) {
+               RAS_DEV_ERR(ras_core->dev, "Failed to translate nps record! 
ret:%d\n", ret);
+               return true;
        }
 
-       for (i = 0; i < data->count; i++) {
-               if ((data->bps[i].retired_row_pfn == record->retired_row_pfn) &&
-                   (data->bps[i].cur_nps_retired_row_pfn == 
record->cur_nps_retired_row_pfn))
-                       return true;
-       }
+       if (ras_umc_check_logged_record(ras_core, record))
+               return true;
 
        return false;
 }
 
+static int ras_umc_log_record(struct ras_core_context *ras_core,
+                               struct eeprom_umc_record *record)
+{
+       struct eeprom_umc_record *rec;
+
+       rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+       if (!rec)
+               return -ENOMEM;
+
+       memcpy(rec, record, sizeof(*rec));
+
+       return ras_umc_log_ecc(ras_core, rec->cur_nps_retired_row_pfn, rec);
+}
+
 /* alloc/realloc bps array */
 static int ras_umc_realloc_err_data_space(struct ras_core_context *ras_core,
                struct eeprom_store_record *data, int pages)
@@ -612,41 +588,41 @@ static void ras_umc_update_bad_pages(struct 
ras_core_context *ras_core)
        data->bad_page_num_old = data->bad_page_num;
 }
 
-/* it deal with vram only. */
-static int ras_umc_add_bad_pages(struct ras_core_context *ras_core,
-                                struct eeprom_umc_record *bps,
-                                int pages, bool from_eeprom)
+int ras_umc_add_bad_pages(struct ras_core_context *ras_core,
+       struct eeprom_umc_record *bps, uint32_t bps_sz, uint32_t *valid_sz)
 {
        struct ras_umc *ras_umc = &ras_core->ras_umc;
-       struct ras_umc_err_data *data = &ras_umc->umc_err_data;
-       int i, ret = 0;
+       uint32_t i, c = 0;
+       int ret = 0;
 
-       if (!bps || pages <= 0)
-               return 0;
+       if (!bps || !bps_sz || !valid_sz)
+               return -EINVAL;
 
        mutex_lock(&ras_umc->umc_lock);
-       for (i = 0; i < pages; i++) {
-               if (ras_umc_check_retired_record(ras_core, &bps[i], 
from_eeprom))
+       for (i = 0; i < bps_sz; i++) {
+               if (ras_umc_check_retired_record(ras_core, &bps[i]))
                        continue;
 
                ret = ras_umc_update_eeprom_rom_data(ras_core, &bps[i]);
                if (ret)
                        goto out;
 
-               if (data->last_retired_pfn == bps[i].cur_nps_retired_row_pfn)
-                       continue;
-
-               data->last_retired_pfn = bps[i].cur_nps_retired_row_pfn;
+               ret = ras_umc_log_record(ras_core, &bps[i]);
+               if (ret)
+                       goto out;
 
-               if (from_eeprom)
-                       ras_umc_reserve_eeprom_record(ras_core, &bps[i]);
+               ras_umc_reserve_eeprom_record(ras_core, &bps[i]);
 
                ret = ras_umc_update_eeprom_ram_data(ras_core, &bps[i]);
                if (ret)
                        goto out;
+               c++;
        }
 
-       ras_eeprom_mgr_check_and_report_status(ras_core, true);
+       *valid_sz = c;
+
+       if (c)
+               ras_eeprom_mgr_check_and_report_status(ras_core, true);
 
 out:
        mutex_unlock(&ras_umc->umc_lock);
@@ -661,7 +637,7 @@ static int ras_umc_add_bad_pages(struct ras_core_context 
*ras_core,
 int ras_umc_load_bad_pages(struct ras_core_context *ras_core)
 {
        struct eeprom_umc_record *bps;
-       uint32_t ras_num_recs;
+       uint32_t ras_num_recs, c = 0;
        int ret;
 
        ras_num_recs = ras_eeprom_mgr_get_record_count(ras_core);
@@ -673,12 +649,11 @@ int ras_umc_load_bad_pages(struct ras_core_context 
*ras_core)
                return -ENOMEM;
 
        ret = ras_eeprom_mgr_get_records(ras_core, 0, bps, ras_num_recs);
-       if (ret) {
+       if (ret)
                RAS_DEV_ERR(ras_core->dev,
                        "Failed to load EEPROM table records! ret:%d\n", ret);
-       } else {
-               ras_core->ras_umc.umc_err_data.last_retired_pfn = 
UMC_INV_MEM_PFN;
-               ret = ras_umc_add_bad_pages(ras_core, bps, ras_num_recs, true);
+       else {
+               ret = ras_umc_add_bad_pages(ras_core, bps, ras_num_recs, &c);
                ras_umc_update_bad_pages(ras_core);
        }
 
@@ -698,10 +673,10 @@ static int ras_umc_save_bad_pages(struct ras_core_context 
*ras_core)
        struct eeprom_store_record *ram_data = &ras_umc->umc_err_data.ram_data;
        uint32_t eeprom_record_num, logical_count = 0;
        int save_count;
-       int ret = 0;
+       int ret = -ENODATA;
 
        if (!data->bps)
-               return 0;
+               return -EINVAL;
 
        eeprom_record_num = ras_eeprom_mgr_get_record_count(ras_core);
        mutex_lock(&ras_umc->umc_lock);
@@ -717,8 +692,9 @@ static int ras_umc_save_bad_pages(struct ras_core_context 
*ras_core)
                        ret = -EIO;
                        goto exit;
                }
+
                ras_umc_update_bad_pages(ras_core);
-               RAS_DEV_INFO(ras_core->dev, "Saved %d pages to EEPROM 
table.\n", logical_count);
+               RAS_DEV_INFO(ras_core->dev, "Saved %d records to EEPROM 
table.\n", logical_count);
        }
 
 exit:
@@ -728,39 +704,7 @@ static int ras_umc_save_bad_pages(struct ras_core_context 
*ras_core)
 
 int ras_umc_handle_bad_pages(struct ras_core_context *ras_core, void *data)
 {
-       struct eeprom_umc_record *records;
-       int count, ret;
-
-       records = kzalloc_objs(*records, MAX_ECC_NUM_PER_RETIREMENT);
-       if (!records)
-               return -ENOMEM;
-
-       count = ras_umc_get_new_records(ras_core, records,
-                                       MAX_ECC_NUM_PER_RETIREMENT);
-       if (count <= 0) {
-               ret = -ENODATA;
-               goto out;
-       }
-
-       ret = ras_umc_add_bad_pages(ras_core, records, count, false);
-       if (ret) {
-               RAS_DEV_ERR(ras_core->dev, "Failed to add ras bad page!\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = ras_umc_save_bad_pages(ras_core);
-       if (ret) {
-               RAS_DEV_ERR(ras_core->dev, "Failed to save ras bad page\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = 0;
-
-out:
-       kfree(records);
-       return ret;
+       return ras_umc_save_bad_pages(ras_core);
 }
 
 int ras_umc_sw_init(struct ras_core_context *ras_core)
@@ -964,3 +908,13 @@ int ras_umc_bank_to_umc_record(struct ras_core_context 
*ras_core,
 
        return 0;
 }
+
+int ras_umc_record_to_nps_record(struct ras_core_context *ras_core,
+               struct eeprom_umc_record *record,  uint32_t nps)
+{
+       if (!record || !nps ||
+               (nps >= UMC_MEMORY_PARTITION_MODE_UNKNOWN))
+               return -EINVAL;
+
+       return ras_umc_eeprom_rec2nps_rec(ras_core, record, nps);
+}
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.h 
b/drivers/gpu/drm/amd/ras/core/ras_umc.h
index ed77fb3912d59..221cd008e55a0 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_umc.h
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc.h
@@ -160,7 +160,6 @@ struct eeprom_store_record {
 struct ras_umc_err_data {
        struct eeprom_store_record rom_data;
        struct eeprom_store_record ram_data;
-       uint64_t last_retired_pfn;
 };
 
 struct ras_umc {
@@ -201,6 +200,8 @@ int ras_umc_log_bad_bank_pending(struct ras_core_context 
*ras_core, struct ras_b
 int ras_umc_log_pending_bad_bank(struct ras_core_context *ras_core);
 int ras_umc_clear_logged_ecc(struct ras_core_context *ras_core);
 int ras_umc_load_bad_pages(struct ras_core_context *ras_core);
+int ras_umc_add_bad_pages(struct ras_core_context *ras_core,
+       struct eeprom_umc_record *bps, uint32_t bps_sz, uint32_t *valid_sz);
 int ras_umc_get_saved_eeprom_count(struct ras_core_context *ras_core);
 int ras_umc_clean_badpage_data(struct ras_core_context *ras_core);
 int ras_umc_fill_eeprom_record(struct ras_core_context *ras_core,
@@ -221,4 +222,6 @@ int ras_umc_ma2pa(struct ras_core_context *ras_core,
        uint32_t nps);
 int ras_umc_bank_to_umc_record(struct ras_core_context *ras_core,
                struct ras_bank_ecc *bank, struct eeprom_umc_record *record);
+int ras_umc_record_to_nps_record(struct ras_core_context *ras_core,
+               struct eeprom_umc_record *record,  uint32_t nps);
 #endif
-- 
2.55.0

Reply via email to