[PATCH 079/109] drm/amd/ras: introduce row page address buffer alloc/free interfaces
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> Introduce row page address buffer alloc/free interfaces. 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/cmd.h | 2 +- drivers/gpu/drm/amd/ras/core/core.c | 11 +- drivers/gpu/drm/amd/ras/core/ras_umc.c | 137 ++++++++++++------- drivers/gpu/drm/amd/ras/core/ras_umc.h | 11 +- drivers/gpu/drm/amd/ras/core/ras_umc_v12_0.c | 3 + 5 files changed, 99 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/cmd.h b/drivers/gpu/drm/amd/ras/core/cmd.h index 728fbe55d1765..a37b050e913ab 100644 --- a/drivers/gpu/drm/amd/ras/core/cmd.h +++ b/drivers/gpu/drm/amd/ras/core/cmd.h @@ -452,7 +452,7 @@ struct ras_cmd_convert_retired_address_req { uint32_t reserved[6]; }; -#define RAS_CMD_MAX_RETIRED_ADDR_COUNT 32 +#define RAS_CMD_MAX_RETIRED_ADDR_COUNT 128 struct ras_cmd_convert_retired_address_rsp { uint32_t version; uint32_t retired_count; diff --git a/drivers/gpu/drm/amd/ras/core/core.c b/drivers/gpu/drm/amd/ras/core/core.c index 00dc6084454cd..71c7c54ddb7c8 100644 --- a/drivers/gpu/drm/amd/ras/core/core.c +++ b/drivers/gpu/drm/amd/ras/core/core.c @@ -700,23 +700,14 @@ int ras_core_convert_soc_pa_to_cur_nps_pages(struct ras_core_context *ras_core, uint64_t soc_pa, uint64_t *page_pfn, uint32_t max_pages) { struct eeprom_umc_record record; - uint32_t cur_nps_mode; - int count = 0; if (!ras_core || !page_pfn || !max_pages) return -EINVAL; - cur_nps_mode = ras_core_get_curr_nps_mode(ras_core); - if (!cur_nps_mode || cur_nps_mode > UMC_MEMORY_PARTITION_MODE_NPS8) - return -EINVAL; - memset(&record, 0, sizeof(record)); record.cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(soc_pa); - count = ras_umc_convert_record_to_nps_pages(ras_core, - &record, cur_nps_mode, page_pfn, max_pages); - - return count; + return ras_umc_convert_record_to_row_pages(ras_core, &record, page_pfn, max_pages); } int ras_core_check_address_sanity(struct ras_core_context *ras_core, diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c b/drivers/gpu/drm/amd/ras/core/ras_umc.c index c30d11942a72b..299426d6d8318 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc.c +++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c @@ -70,11 +70,15 @@ static uint64_t ras_umc_get_eeprom_timestamp(struct ras_core_context *ras_core) static const struct ras_umc_ip_func *ras_umc_get_ip_func( struct ras_core_context *ras_core, uint32_t ip_version) { + struct ras_umc *ras_umc = &ras_core->ras_umc; + switch (ip_version) { case IP_VERSION(12, 0, 0): case IP_VERSION(12, 5, 0): + ras_umc->max_pages_per_row = 16; return &ras_umc_func_v12_0; case IP_VERSION(15, 0, 0): + ras_umc->max_pages_per_row = 128; return &ras_umc_func_v15_0; default: RAS_DEV_ERR(ras_core->dev, @@ -177,6 +181,44 @@ int ras_umc_clear_logged_ecc(struct ras_core_context *ras_core) return 0; } +int ras_umc_alloc_row_pages(struct ras_core_context *ras_core, + uint64_t **page_pfns, uint32_t *nr_page_pfns) +{ + struct ras_umc *ras_umc = &ras_core->ras_umc; + uint64_t *address; + uint64_t page_num; + + if (!page_pfns || !nr_page_pfns) + return -EINVAL; + + if (!ras_umc->max_pages_per_row) { + RAS_DEV_ERR(ras_core->dev, "max_pages_per_row was not initialized!\n"); + return -EPERM; + } + + page_num = ras_umc->max_pages_per_row; + + address = kcalloc(page_num, sizeof(*address), GFP_KERNEL); + if (!address) + return -ENOMEM; + + *page_pfns = address; + *nr_page_pfns = page_num; + + return 0; +} + +int ras_umc_free_row_pages(struct ras_core_context *ras_core, + uint64_t *page_pfns) +{ + if (!page_pfns) + return -EINVAL; + + kfree(page_pfns); + + return 0; +} + static int ras_umc_expand_row_pages(struct ras_core_context *ras_core, struct eeprom_umc_record *record, uint64_t *page_pfns, uint32_t nr_page_pfns) { @@ -209,9 +251,8 @@ static int ras_umc_expand_row_pages(struct ras_core_context *ras_core, return count; } -int ras_umc_convert_record_to_nps_pages(struct ras_core_context *ras_core, - struct eeprom_umc_record *record, uint32_t nps, - uint64_t *page_pfns, uint32_t nr_page_pfns) +int ras_umc_convert_record_to_row_pages(struct ras_core_context *ras_core, + struct eeprom_umc_record *record, uint64_t *page_pfns, uint32_t nr_page_pfns) { uint32_t new_nps; int ret, count = 0; @@ -236,26 +277,21 @@ int ras_umc_convert_record_to_nps_pages(struct ras_core_context *ras_core, return count; } -static void ras_umc_reserve_eeprom_record(struct ras_core_context *ras_core, - struct eeprom_umc_record *record) +static void ras_umc_reserve_row_pages(struct ras_core_context *ras_core, + struct eeprom_umc_record *record, uint64_t *pages, uint32_t nr_pages) { - uint64_t page_pfn[16]; - int count = 0, i; + struct ras_umc *ras_umc = &ras_core->ras_umc; + int i; - memset(page_pfn, 0, sizeof(page_pfn)); - count = ras_umc_convert_record_to_nps_pages(ras_core, - record, record->cur_nps, page_pfn, ARRAY_SIZE(page_pfn)); - if (count <= 0) { - RAS_DEV_ERR(ras_core->dev, - "Fail to convert error address! count:%d\n", count); + if (!pages || !nr_pages || + (nr_pages > ras_umc->max_pages_per_row)) return; - } /* Reserve memory */ - for (i = 0; i < count; i++) + for (i = 0; i < nr_pages; i++) ras_core_event_notify(ras_core, ras_core_in_early_init(ras_core) ? RAS_EVENT_ID__EARLY_INIT_RESERVE_PAGE : RAS_EVENT_ID__RESERVE_BAD_PAGE, - &page_pfn[i]); + &pages[i]); } /* When gpu reset is ongoing, ecc logging operations will be pended. @@ -614,44 +650,25 @@ static int ras_umc_update_eeprom_rom_data(struct ras_core_context *ras_core, } static int ras_umc_update_eeprom_ram_data(struct ras_core_context *ras_core, - struct eeprom_umc_record *bps) + struct eeprom_umc_record *bps, uint64_t *page_pfns, uint32_t nr_page_pfns) { struct ras_umc *ras_umc = &ras_core->ras_umc; struct eeprom_store_record *data = &ras_umc->umc_err_data.ram_data; - uint64_t page_pfn[16]; - int count = 0, i, j; + int j; + + if (!bps || !page_pfns || !nr_page_pfns || + (nr_page_pfns > ras_umc->max_pages_per_row)) + return -EINVAL; if (!data->space_left && - ras_umc_realloc_err_data_space(ras_core, data, 256)) { - return -ENOMEM; - } + ras_umc_realloc_err_data_space(ras_core, data, 256)) + return -ENOMEM; - memset(page_pfn, 0, sizeof(page_pfn)); - count = ras_umc_convert_record_to_nps_pages(ras_core, - bps, bps->cur_nps, page_pfn, ARRAY_SIZE(page_pfn)); - if (count > 0) { - for (j = 0; j < count; j++) { - if (ras_core_check_address_sanity(ras_core, - page_pfn[j] << AMDGPU_GPU_PAGE_SHIFT)) { - - for (i = 0; i < data->count; i++) - if (page_pfn[j] == data->bps[i].cur_nps_retired_row_pfn) - break; - data->bps[data->count].cur_nps_retired_row_pfn = U64_MAX; - data->count++; - data->space_left--; - continue; - } - - bps->cur_nps_retired_row_pfn = page_pfn[j]; - memcpy(&data->bps[data->count], bps, sizeof(*data->bps)); - data->count++; - data->space_left--; - data->bad_page_num++; - } - } else { - RAS_DEV_ERR(ras_core->dev, "Failed to convert record to nps pages!"); - return -EINVAL; + for (j = 0; j < nr_page_pfns; j++) { + bps->cur_nps_retired_row_pfn = page_pfns[j]; + memcpy(&data->bps[data->count], bps, sizeof(*data->bps)); + data->count++; + data->space_left--; } /* update bad channel bitmap */ @@ -694,17 +711,33 @@ 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; + uint64_t *page_pfns = NULL; + uint32_t nr_page_pfns = 0; + int nr_valid_pfns = 0; uint32_t i, c = 0; int ret = 0; if (!bps || !bps_sz || !valid_sz) return -EINVAL; + ret = ras_umc_alloc_row_pages(ras_core, &page_pfns, &nr_page_pfns); + if (ret) + return ret; + mutex_lock(&ras_umc->umc_lock); for (i = 0; i < bps_sz; i++) { if (ras_umc_check_retired_record(ras_core, &bps[i])) continue; + nr_valid_pfns = ras_umc_convert_record_to_row_pages(ras_core, + &bps[i], page_pfns, nr_page_pfns); + if (nr_valid_pfns < 0) { + RAS_DEV_ERR(ras_core->dev, + "Failed to lookup record bad pages! %d\n", nr_valid_pfns); + ret = nr_valid_pfns; + goto out; + } + ret = ras_umc_update_eeprom_rom_data(ras_core, &bps[i]); if (ret) goto out; @@ -713,9 +746,11 @@ int ras_umc_add_bad_pages(struct ras_core_context *ras_core, if (ret) goto out; - ras_umc_reserve_eeprom_record(ras_core, &bps[i]); + ras_umc_reserve_row_pages(ras_core, + &bps[i], page_pfns, nr_valid_pfns); - ret = ras_umc_update_eeprom_ram_data(ras_core, &bps[i]); + ret = ras_umc_update_eeprom_ram_data(ras_core, + &bps[i], page_pfns, nr_valid_pfns); if (ret) goto out; c++; @@ -731,7 +766,7 @@ int ras_umc_add_bad_pages(struct ras_core_context *ras_core, out: mutex_unlock(&ras_umc->umc_lock); - + ras_umc_free_row_pages(ras_core, page_pfns); return ret; } diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.h b/drivers/gpu/drm/amd/ras/core/ras_umc.h index b52480ba886b8..362c9ce6a404b 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc.h +++ b/drivers/gpu/drm/amd/ras/core/ras_umc.h @@ -183,6 +183,8 @@ struct ras_umc { u32 last_record_count; u64 last_channel_bitmap; + + u32 max_pages_per_row; }; /* @@ -222,9 +224,8 @@ int ras_umc_get_badpage_record(struct ras_core_context *ras_core, uint32_t index bool ras_umc_check_retired_addr(struct ras_core_context *ras_core, uint64_t addr); int ras_umc_translate_soc_pa_and_bank(struct ras_core_context *ras_core, uint64_t *soc_pa, struct umc_bank_addr *bank_addr, bool bank_to_pa); -int ras_umc_convert_record_to_nps_pages(struct ras_core_context *ras_core, - struct eeprom_umc_record *record, uint32_t nps, - uint64_t *page_pfn, uint32_t max_pages); +int ras_umc_convert_record_to_row_pages(struct ras_core_context *ras_core, + struct eeprom_umc_record *record, uint64_t *page_addrs, uint32_t nr_page_addrs); uint32_t ras_umc_bit_wise_xor(uint32_t val); int ras_umc_ma2pa(struct ras_core_context *ras_core, struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out, @@ -235,4 +236,8 @@ int ras_umc_record_to_nps_record(struct ras_core_context *ras_core, struct eeprom_umc_record *record, uint32_t nps); int ras_umc_dump_fw_records(struct ras_core_context *ras_core); void ras_umc_report_badpage_info(struct ras_core_context *ras_core); +int ras_umc_alloc_row_pages(struct ras_core_context *ras_core, + uint64_t **page_pfns, uint32_t *nr_page_pfns); +int ras_umc_free_row_pages(struct ras_core_context *ras_core, + uint64_t *page_pfns); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc_v12_0.c b/drivers/gpu/drm/amd/ras/core/ras_umc_v12_0.c index 37fa24acddd02..c637ad9314103 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc_v12_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_umc_v12_0.c @@ -473,6 +473,9 @@ static int umc_v12_0_eeprom_record_to_nps_record(struct ras_core_context *ras_co uint64_t row_pfn; int ret = 0; + if (!record || !nps) + return -EINVAL; + if (nps == EEPROM_RECORD_UMC_NPS_MODE(record)) { record->cur_nps_pa_flip_mask = __get_nps_pa_flip_mask(ras_core, nps); row_pfn = EEPROM_RECORD_UMC_ADDR_PFN(record); -- 2.55.0