From 0153d27673ac5c122d2437c1e573923963abd181 Mon Sep 17 00:00:00 2001 From: ganglxie Date: Mon, 24 Feb 2025 15:03:05 +0800 Subject: drm/amdgpu: Refine bad page adding bad page adding can be simpler with nps info Signed-off-by: ganglxie Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 196 +++++++++++++++++--------------- 1 file changed, 104 insertions(+), 92 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 3c3312bbfee8..f0349094f8c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2799,20 +2799,100 @@ static int amdgpu_ras_mca2pa(struct amdgpu_device *adev, return -EINVAL; } +static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev, + struct eeprom_table_record *bps, int count) +{ + int j; + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_err_handler_data *data = con->eh_data; + + for (j = 0; j < count; j++) { + if (amdgpu_ras_check_bad_page_unlock(con, + bps[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) + continue; + + if (!data->space_left && + amdgpu_ras_realloc_eh_data_space(adev, data, 256)) { + return -ENOMEM; + } + + amdgpu_ras_reserve_page(adev, bps[j].retired_page); + + memcpy(&data->bps[data->count], &(bps[j]), + sizeof(struct eeprom_table_record)); + data->count++; + data->space_left--; + } + + return 0; +} + +static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev, + struct eeprom_table_record *bps, struct ras_err_data *err_data, + enum amdgpu_memory_partition nps) +{ + int i = 0; + enum amdgpu_memory_partition save_nps; + + save_nps = (bps[0].retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; + + for (i = 0; i < adev->umc.retire_unit; i++) + bps[i].retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); + + if (save_nps) { + if (save_nps == nps) { + if (amdgpu_umc_pages_in_a_row(adev, err_data, + bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT)) + return -EINVAL; + } else { + if (amdgpu_ras_mca2pa_by_idx(adev, &bps[0], err_data)) + return -EINVAL; + } + } else { + if (amdgpu_ras_mca2pa(adev, &bps[0], err_data)) { + if (nps == AMDGPU_NPS1_PARTITION_MODE) + memcpy(err_data->err_addr, bps, + sizeof(struct eeprom_table_record) * adev->umc.retire_unit); + else + return -EOPNOTSUPP; + } + } + + return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr, adev->umc.retire_unit); +} + +static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev, + struct eeprom_table_record *bps, struct ras_err_data *err_data, + enum amdgpu_memory_partition nps) +{ + enum amdgpu_memory_partition save_nps; + + save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; + bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); + + if (save_nps == nps) { + if (amdgpu_umc_pages_in_a_row(adev, err_data, + bps->retired_page << AMDGPU_GPU_PAGE_SHIFT)) + return -EINVAL; + } else { + if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data)) + return -EINVAL; + } + return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr, + adev->umc.retire_unit); +} + /* it deal with vram only. */ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, struct eeprom_table_record *bps, int pages, bool from_rom) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct ras_err_handler_data *data; struct ras_err_data err_data; - struct eeprom_table_record *err_rec; struct amdgpu_ras_eeprom_control *control = &adev->psp.ras_context.ras->eeprom_control; enum amdgpu_memory_partition nps = AMDGPU_NPS1_PARTITION_MODE; int ret = 0; - uint32_t i, j, loop_cnt = 1; - bool find_pages_per_pa = false; + uint32_t i; if (!con || !con->eh_data || !bps || pages <= 0) return 0; @@ -2823,114 +2903,46 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, sizeof(struct eeprom_table_record), GFP_KERNEL); if (!err_data.err_addr) { dev_warn(adev->dev, "Failed to alloc UMC error address record in mca2pa conversion!\n"); - ret = -ENOMEM; - goto out; + return -ENOMEM; } - err_rec = err_data.err_addr; - loop_cnt = adev->umc.retire_unit; if (adev->gmc.gmc_funcs->query_mem_partition_mode) nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev); } mutex_lock(&con->recovery_lock); - data = con->eh_data; - if (!data) { - /* Returning 0 as the absence of eh_data is acceptable */ - goto free; - } - - for (i = 0; i < pages; i++) { - if (from_rom && - control->rec_type == AMDGPU_RAS_EEPROM_REC_MCA) { - if (!find_pages_per_pa) { - if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) { - if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) { - /* may use old RAS TA, use PA to find pages in - * one row - */ - if (amdgpu_umc_pages_in_a_row(adev, &err_data, - bps[i].retired_page << - AMDGPU_GPU_PAGE_SHIFT)) { - ret = -EINVAL; - goto free; - } else { - find_pages_per_pa = true; - } - } else { - /* unsupported cases */ - ret = -EOPNOTSUPP; - goto free; - } - } - } else { - if (amdgpu_umc_pages_in_a_row(adev, &err_data, - bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT)) { - ret = -EINVAL; - goto free; - } - } - } else { - if (from_rom && !find_pages_per_pa) { - if (bps[i].retired_page & UMC_CHANNEL_IDX_V2) { - /* bad page in any NPS mode in eeprom */ - if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) { - ret = -EINVAL; + + if (from_rom) { + for (i = 0; i < pages; i++) { + if (control->ras_num_recs - i >= adev->umc.retire_unit) { + if ((bps[i].address == bps[i + 1].address) && + (bps[i].mem_channel == bps[i + 1].mem_channel)) { + //deal with retire_unit records a time + ret = __amdgpu_ras_convert_rec_array_from_rom(adev, + &bps[i], &err_data, nps); + if (ret) goto free; - } + i += (adev->umc.retire_unit - 1); } else { - /* legacy bad page in eeprom, generated only in - * NPS1 mode - */ - if (amdgpu_ras_mca2pa(adev, &bps[i], &err_data)) { - /* old RAS TA or ASICs which don't support to - * convert addrss via mca address - */ - if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) { - find_pages_per_pa = true; - err_rec = &bps[i]; - loop_cnt = 1; - } else { - /* non-nps1 mode, old RAS TA - * can't support it - */ - ret = -EOPNOTSUPP; - goto free; - } - } + break; } - - if (!find_pages_per_pa) - i += (adev->umc.retire_unit - 1); } else { - err_rec = &bps[i]; + break; } } - - for (j = 0; j < loop_cnt; j++) { - if (amdgpu_ras_check_bad_page_unlock(con, - err_rec[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) - continue; - - if (!data->space_left && - amdgpu_ras_realloc_eh_data_space(adev, data, 256)) { - ret = -ENOMEM; + for (; i < pages; i++) { + ret = __amdgpu_ras_convert_rec_from_rom(adev, + &bps[i], &err_data, nps); + if (ret) goto free; - } - - amdgpu_ras_reserve_page(adev, err_rec[j].retired_page); - - memcpy(&data->bps[data->count], &(err_rec[j]), - sizeof(struct eeprom_table_record)); - data->count++; - data->space_left--; } + } else { + ret = __amdgpu_ras_restore_bad_pages(adev, bps, pages); } free: if (from_rom) kfree(err_data.err_addr); -out: mutex_unlock(&con->recovery_lock); return ret; -- cgit v1.2.3 From a8f921a10a8c2e2b209ad9ed1f1b7f48192c30aa Mon Sep 17 00:00:00 2001 From: ganglxie Date: Mon, 24 Feb 2025 15:06:51 +0800 Subject: drm/amdgpu: Change page/record number calculation based on nps save only one record to save eeprom space,and bad_page_num = pa_rec_num + mca_rec_num*16 Signed-off-by: ganglxie Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 49 ++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 17 ++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 20 ++++------- 3 files changed, 35 insertions(+), 51 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f0349094f8c9..493dd004d6fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2981,24 +2981,14 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev, /* only new entries are saved */ if (save_count > 0) { - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) { + for (i = 0; i < unit_num; i++) { if (amdgpu_ras_eeprom_append(control, - &data->bps[control->ras_num_recs], - save_count)) { + &data->bps[bad_page_num + i * adev->umc.retire_unit], + 1)) { dev_err(adev->dev, "Failed to save EEPROM table data!"); return -EIO; } - } else { - for (i = 0; i < unit_num; i++) { - if (amdgpu_ras_eeprom_append(control, - &data->bps[bad_page_num + i * adev->umc.retire_unit], - 1)) { - dev_err(adev->dev, "Failed to save EEPROM table data!"); - return -EIO; - } - } } - dev_info(adev->dev, "Saved %d pages to EEPROM table.\n", save_count); } @@ -3014,7 +3004,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) struct amdgpu_ras_eeprom_control *control = &adev->psp.ras_context.ras->eeprom_control; struct eeprom_table_record *bps; - int ret; + int ret, i = 0; /* no bad page record, skip eeprom access */ if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0) @@ -3028,13 +3018,23 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) if (ret) { dev_err(adev->dev, "Failed to load EEPROM table records!"); } else { - if (control->ras_num_recs > 1 && - adev->umc.ras && adev->umc.ras->convert_ras_err_addr) { - if ((bps[0].address == bps[1].address) && - (bps[0].mem_channel == bps[1].mem_channel)) - control->rec_type = AMDGPU_RAS_EEPROM_REC_PA; - else - control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA; + if (adev->umc.ras && adev->umc.ras->convert_ras_err_addr) { + for (i = 0; i < control->ras_num_recs; i++) { + if ((control->ras_num_recs - i) >= adev->umc.retire_unit) { + if ((bps[i].address == bps[i + 1].address) && + (bps[i].mem_channel == bps[i + 1].mem_channel)) { + control->ras_num_pa_recs += adev->umc.retire_unit; + i += (adev->umc.retire_unit - 1); + } else { + control->ras_num_mca_recs += + (control->ras_num_recs - i); + break; + } + } else { + control->ras_num_mca_recs += (control->ras_num_recs - i); + break; + } + } } ret = amdgpu_ras_eeprom_check(control); @@ -3440,12 +3440,7 @@ int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev) return ret; if (!adev->umc.ras || !adev->umc.ras->convert_ras_err_addr) - control->rec_type = AMDGPU_RAS_EEPROM_REC_PA; - - /* default status is MCA storage */ - if (control->ras_num_recs <= 1 && - adev->umc.ras && adev->umc.ras->convert_ras_err_addr) - control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA; + control->ras_num_pa_recs = control->ras_num_recs; if (control->ras_num_recs) { ret = amdgpu_ras_load_bad_pages(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 87fcdda3ec61..ab27cecb5519 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -727,11 +727,9 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control, - control->ras_fri) % control->ras_max_record_count; - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) - control->ras_num_bad_pages = control->ras_num_recs; - else - control->ras_num_bad_pages = - control->ras_num_recs * adev->umc.retire_unit; + control->ras_num_mca_recs += num; + control->ras_num_bad_pages += num * adev->umc.retire_unit; + Out: kfree(buf); return res; @@ -1396,6 +1394,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) } control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset); + control->ras_num_mca_recs = 0; + control->ras_num_pa_recs = 0; return 0; } @@ -1416,11 +1416,8 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control) if (!__get_eeprom_i2c_addr(adev, control)) return -EINVAL; - if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) - control->ras_num_bad_pages = control->ras_num_recs; - else - control->ras_num_bad_pages = - control->ras_num_recs * adev->umc.retire_unit; + control->ras_num_bad_pages = control->ras_num_pa_recs + + control->ras_num_mca_recs * adev->umc.retire_unit; if (hdr->header == RAS_TABLE_HDR_VAL) { DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 81d55cb7b397..13f7eda9a696 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -43,19 +43,6 @@ enum amdgpu_ras_eeprom_err_type { AMDGPU_RAS_EEPROM_ERR_COUNT, }; -/* - * one UMC MCA address could map to multiply physical address (PA), - * such as 1:16, we use eeprom_table_record.address to store MCA - * address and use eeprom_table_record.retired_page to save PA. - * - * AMDGPU_RAS_EEPROM_REC_PA: one record store one PA - * AMDGPU_RAS_EEPROM_REC_MCA: one record store one MCA address - */ -enum amdgpu_ras_eeprom_rec_type { - AMDGPU_RAS_EEPROM_REC_PA, - AMDGPU_RAS_EEPROM_REC_MCA, -}; - struct amdgpu_ras_eeprom_table_header { uint32_t header; uint32_t version; @@ -100,6 +87,12 @@ struct amdgpu_ras_eeprom_control { */ u32 ras_num_bad_pages; + /* Number of records store mca address */ + u32 ras_num_mca_recs; + + /* Number of records store physical address */ + u32 ras_num_pa_recs; + /* First record index to read, 0-based. * Range is [0, num_recs-1]. This is * an absolute index, starting right after @@ -120,7 +113,6 @@ struct amdgpu_ras_eeprom_control { /* Record channel info which occurred bad pages */ u32 bad_channel_bitmap; - enum amdgpu_ras_eeprom_rec_type rec_type; }; /* -- cgit v1.2.3 From d4bd7a50ca7c6199438cf19063464b4d6327a6c1 Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Wed, 26 Feb 2025 14:27:27 +0800 Subject: drm/amdgpu: Report generic instead of unknown boot time errors Change the DMESG reporting of unknown errors to "Boot Controller Generic Error" to align with the RAS SPEC and provide more clarity to customers. Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 493dd004d6fa..285e3aa2bb2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -5138,9 +5138,9 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, "socket: %d, aid: %d, fw_status: 0x%x, data abort exception\n", socket_id, aid_id, fw_status); - if (AMDGPU_RAS_GPU_ERR_UNKNOWN(boot_error)) + if (AMDGPU_RAS_GPU_ERR_GENERIC(boot_error)) dev_info(adev->dev, - "socket: %d, aid: %d, fw_status: 0x%x, unknown boot time errors\n", + "socket: %d, aid: %d, fw_status: 0x%x, Boot Controller Generic Error\n", socket_id, aid_id, fw_status); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index cc4586581dba..764e9fa0a914 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -47,7 +47,7 @@ struct amdgpu_iv_entry; #define AMDGPU_RAS_GPU_ERR_AID_ID(x) AMDGPU_GET_REG_FIELD(x, 12, 11) #define AMDGPU_RAS_GPU_ERR_HBM_ID(x) AMDGPU_GET_REG_FIELD(x, 14, 13) #define AMDGPU_RAS_GPU_ERR_DATA_ABORT(x) AMDGPU_GET_REG_FIELD(x, 29, 29) -#define AMDGPU_RAS_GPU_ERR_UNKNOWN(x) AMDGPU_GET_REG_FIELD(x, 30, 30) +#define AMDGPU_RAS_GPU_ERR_GENERIC(x) AMDGPU_GET_REG_FIELD(x, 30, 30) #define AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT 100 #define AMDGPU_RAS_BOOT_STEADY_STATUS 0xBA -- cgit v1.2.3