[PATCH 046/109] drm/amd/ras: unify umc record logging paths for runtime and preload
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
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