[PATCH 042/109] drm/amd/ras: Refactor EEPROM parameter config to support multiple ras EEPROMs
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> - Refactor EEPROM parameter config to support multiple ras EEPROMs. - Convert bad page count to record count as EEPROM threshold. 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.c | 48 ++++--- drivers/gpu/drm/amd/ras/core/ras.h | 26 +++- .../amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c | 117 +++++++++++++++--- .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c | 67 ---------- 4 files changed, 154 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/eeprom.c b/drivers/gpu/drm/amd/ras/core/eeprom.c index 1bc409048e732..7913cdbdb8b0a 100644 --- a/drivers/gpu/drm/amd/ras/core/eeprom.c +++ b/drivers/gpu/drm/amd/ras/core/eeprom.c @@ -161,16 +161,12 @@ static bool __is_ras_eeprom_supported(struct ras_core_context *ras_core) static bool __get_eeprom_i2c_addr(struct ras_core_context *ras_core, struct ras_eeprom_control *control) { - int ret = -EINVAL; - - if (control->sys_func && - control->sys_func->update_eeprom_i2c_config) - ret = control->sys_func->update_eeprom_i2c_config(ras_core); - else - RAS_DEV_WARN(ras_core->dev, - "No eeprom i2c system config!\n"); + if (!control->i2c_address) { + RAS_DEV_WARN(ras_core->dev, "Not config eeprom i2c address!\n"); + return false; + } - return !ret ? true : false; + return true; } static int __ras_eeprom_xfer(struct ras_core_context *ras_core, u32 eeprom_addr, @@ -1286,6 +1282,8 @@ int ras_eeprom_hw_init(struct ras_core_context *ras_core) { struct ras_eeprom_control *control; struct ras_eeprom_config *eeprom_cfg; + struct ras_eeprom_param_config param_config = {0}; + int ret; if (!ras_core) return -EINVAL; @@ -1297,21 +1295,35 @@ int ras_eeprom_hw_init(struct ras_core_context *ras_core) memset(control, 0, sizeof(*control)); eeprom_cfg = &ras_core->config->eeprom_cfg; + if (!eeprom_cfg || !eeprom_cfg->eeprom_sys_fn || + !eeprom_cfg->eeprom_sys_fn->get_eeprom_config) { + RAS_DEV_ERR(ras_core->dev, "Ras eeprom not configured!\n"); + return -EINVAL; + } + + control->sys_func = eeprom_cfg->eeprom_sys_fn; + + ret = eeprom_cfg->eeprom_sys_fn->get_eeprom_config(ras_core, + ¶m_config); + if (ret) { + RAS_DEV_ERR(ras_core->dev, "Failed to get ras eeprom config!\n"); + return -EPERM; + } + control->record_threshold_config = - eeprom_cfg->eeprom_record_threshold_config; + param_config.eeprom_record_threshold_config; control->record_threshold_count = ras_eeprom_max_record_count(ras_core); - if (eeprom_cfg->eeprom_record_threshold_count < + if (param_config.eeprom_record_threshold_count < control->record_threshold_count) control->record_threshold_count = - eeprom_cfg->eeprom_record_threshold_count; + param_config.eeprom_record_threshold_count; - control->sys_func = eeprom_cfg->eeprom_sys_fn; - control->max_read_len = eeprom_cfg->max_i2c_read_len; - control->max_write_len = eeprom_cfg->max_i2c_write_len; - control->i2c_adapter = eeprom_cfg->eeprom_i2c_adapter; - control->i2c_port = eeprom_cfg->eeprom_i2c_port; - control->i2c_address = eeprom_cfg->eeprom_i2c_addr; + control->max_read_len = param_config.max_i2c_read_len; + control->max_write_len = param_config.max_i2c_write_len; + control->i2c_adapter = param_config.eeprom_i2c_adapter; + control->i2c_port = param_config.eeprom_i2c_port; + control->i2c_address = param_config.eeprom_i2c_addr; control->update_channel_flag = false; diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index 10fa7068fc7a4..9c87037454d5c 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -27,7 +27,7 @@ #include "ras_sys.h" #include "ras_umc.h" #include "aca.h" -#include "eeprom.h" +#include "ras_eeprom_mgr.h" #include "core_status.h" #include "ras_process.h" #include "ras_gfx.h" @@ -185,6 +185,13 @@ enum ras_unit_id { RAS_UNIT_ID_MAX }; +enum ras_work_mode_over_thresh { + RAS_WORK_MODE_OVER_THRESH_STRICT, + RAS_WORK_MODE_OVER_THRESH_NORMAL, + RAS_WORK_MODE_OVER_THRESH_DEBUG, + RAS_WORK_MODE_OVER_THRESH_RMA, +}; + struct ras_core_context; struct ras_bank_ecc; struct ras_umc; @@ -193,6 +200,7 @@ struct ras_process; struct ras_nbio; struct ras_log_ring; struct ras_psp; +struct ras_eeprom_mgr; struct ras_mp1_sys_func { int (*mp1_get_valid_bank_count)(struct ras_core_context *ras_core, @@ -206,10 +214,23 @@ struct ras_mp1_sys_func { int (*mp1_set_debug_mode)(struct ras_core_context *ras_core, bool enable); }; +struct ras_eeprom_param_config { + int eeprom_record_threshold_config; + u32 eeprom_ip_version; + u64 eeprom_record_threshold_count; + enum ras_work_mode_over_thresh work_mode_over_thresh; + void *eeprom_i2c_adapter; + u32 eeprom_i2c_addr; + u32 eeprom_i2c_port; + u16 max_i2c_read_len; + u16 max_i2c_write_len; +}; + struct ras_eeprom_sys_func { int (*eeprom_i2c_xfer)(struct ras_core_context *ras_core, u32 eeprom_addr, u8 *eeprom_buf, u32 buf_size, bool read); - int (*update_eeprom_i2c_config)(struct ras_core_context *ras_core); + int (*get_eeprom_config)(struct ras_core_context *ras_core, + struct ras_eeprom_param_config *param_cfg); }; struct ras_nbio_sys_func { @@ -363,6 +384,7 @@ 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; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c index aa97b58c94227..14817de696a39 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c @@ -26,6 +26,7 @@ #include "amdgpu_ras_eeprom.h" #include "amdgpu_ras_mgr.h" #include "amdgpu_ras_eeprom_i2c.h" +#include "ras.h" #include "eeprom.h" /* These are memory addresses as would be seen by one or more EEPROM @@ -61,11 +62,30 @@ #define EEPROM_OFFSET_SIZE 2 -static int ras_eeprom_i2c_config(struct ras_core_context *ras_core) +/* typical ras bad page rate is 1 bad page per 100MB VRAM */ +#define ESTIMATE_BAD_PAGE_THRESHOLD(size) div64_u64(size, 100ULL * SZ_1M) + +#define COUNT_BAD_PAGE_THRESHOLD(size) (((size) >> 21) << 4) + +/* Reserve 8 physical dram row for possible retirement. + * In worst cases, it will lose 8 * 2MB memory in vram domain + */ +#define RAS_RESERVED_VRAM_SIZE_DEFAULT (16ULL << 20) + +#define RAS_PAGES_TO_EEPROM_RECORDS(pages, ratio) div64_u64(pages, ratio) + +#define BAD_PAGE_NUM_PER_EEPROM_RECORD_V13 16 +#define BAD_PAGE_NUM_PER_EEPROM_RECORD_V15 128 + +static int ras_eeprom_i2c_config(struct ras_core_context *ras_core, + struct ras_eeprom_param_config *cfg) { struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - struct ras_eeprom_control *control = &ras_core->ras_eeprom; + u64 badpages, badpages_per_record = 0; u8 i2c_addr; + u32 ip_version; + + ip_version = amdgpu_ip_version(adev, MP1_HWIP, 0); if (adev->bios && amdgpu_atomfirmware_ras_rom_addr(adev, &i2c_addr)) { /* The address given by VBIOS is an 8-bit, wire-format @@ -77,28 +97,91 @@ static int ras_eeprom_i2c_config(struct ras_core_context *ras_core) * amdgpu_eeprom.c. */ i2c_addr = (i2c_addr & 0x0F) >> 1; - control->i2c_address = ((u32) i2c_addr) << 16; - return 0; + cfg->eeprom_i2c_addr = ((u32) i2c_addr) << 16; + } else { + switch (ip_version) { + case IP_VERSION(13, 0, 5): + case IP_VERSION(13, 0, 6): + case IP_VERSION(13, 0, 10): + case IP_VERSION(13, 0, 12): + case IP_VERSION(13, 0, 14): + cfg->eeprom_i2c_addr = EEPROM_I2C_MADDR_4; + badpages_per_record = BAD_PAGE_NUM_PER_EEPROM_RECORD_V13; + break; + case IP_VERSION(15, 0, 8): + cfg->eeprom_i2c_addr = EEPROM_I2C_MADDR_4; + badpages_per_record = BAD_PAGE_NUM_PER_EEPROM_RECORD_V15; + break; + default: + RAS_DEV_ERR(adev, "IP version(0x%x) is not supported!\n", ip_version); + return -ENODATA; + } } - switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { - case IP_VERSION(13, 0, 5): - case IP_VERSION(13, 0, 6): - case IP_VERSION(13, 0, 10): - case IP_VERSION(13, 0, 12): - case IP_VERSION(13, 0, 14): - control->i2c_address = EEPROM_I2C_MADDR_4; - return 0; - default: - return -ENODATA; + if (!badpages_per_record || !cfg->eeprom_i2c_addr) { + RAS_DEV_ERR(adev, "EEPROM parameters are not configured!\n"); + return -EINVAL; } - return -ENODATA; + + cfg->eeprom_ip_version = ip_version; + + cfg->eeprom_i2c_adapter = adev->pm.ras_eeprom_i2c_bus; + if (cfg->eeprom_i2c_adapter) { + const struct i2c_adapter_quirks *quirks = + ((struct i2c_adapter *)cfg->eeprom_i2c_adapter)->quirks; + + if (quirks) { + cfg->max_i2c_read_len = quirks->max_read_len; + cfg->max_i2c_write_len = quirks->max_write_len; + } + } + + /* + * amdgpu_bad_page_threshold is used to config + * the threshold for the number of bad pages. + * -1: Threshold is set to default value + * Driver will issue a warning message when threshold is reached + * and continue runtime services. + * 0: Disable bad page retirement + * Driver will not retire bad pages + * which is intended for debugging purpose. + * -2: Threshold is determined by a formula + * that assumes 1 bad page per 100M of local memory. + * Driver will continue runtime services when threhold is reached. + * 0 < threshold < max number of bad page records in EEPROM, + * A user-defined threshold is set + * Driver will halt runtime services when this custom threshold is reached. + */ + if (amdgpu_bad_page_threshold == NONSTOP_OVER_THRESHOLD) { + cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_NORMAL; + badpages = ESTIMATE_BAD_PAGE_THRESHOLD(adev->gmc.mc_vram_size); + } else if (amdgpu_bad_page_threshold == WARN_NONSTOP_OVER_THRESHOLD) { + cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_STRICT; + badpages = COUNT_BAD_PAGE_THRESHOLD(RAS_RESERVED_VRAM_SIZE_DEFAULT); + } else if (!amdgpu_bad_page_threshold) { + cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_DEBUG; + badpages = 128; + } else if (amdgpu_bad_page_threshold > 0) { + cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_RMA; + badpages = amdgpu_bad_page_threshold; + } else { + RAS_DEV_ERR(adev, "Invalid amdgpu_bad_page_threshold value(%d)\n", + amdgpu_bad_page_threshold); + return -EINVAL; + } + + /* Convert bad page count to record count as the threshold value */ + cfg->eeprom_record_threshold_count = + RAS_PAGES_TO_EEPROM_RECORDS(badpages, badpages_per_record); + + return 0; } static int ras_eeprom_i2c_xfer(struct ras_core_context *ras_core, u32 eeprom_addr, u8 *eeprom_buf, u32 buf_size, bool read) { - struct i2c_adapter *i2c_adap = ras_core->ras_eeprom.i2c_adapter; + struct ras_eeprom_control *control = ras_core->eeprom_mgr.ras_eeprom; + struct i2c_adapter *i2c_adap = control->i2c_adapter; u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE]; struct i2c_msg msgs[] = { { @@ -178,5 +261,5 @@ static int ras_eeprom_i2c_xfer(struct ras_core_context *ras_core, u32 eeprom_add const struct ras_eeprom_sys_func amdgpu_ras_eeprom_i2c_sys_func = { .eeprom_i2c_xfer = ras_eeprom_i2c_xfer, - .update_eeprom_i2c_config = ras_eeprom_i2c_config, + .get_eeprom_config = ras_eeprom_i2c_config, }; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c index c71bd447d1b2c..348b0412e5d90 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c @@ -43,17 +43,11 @@ #define MAX_AID_NUM_PER_SOCKET_GFX12 2 #define MAX_XCD_NUM_PER_AID_GFX12 4 -/* typical ECC bad page rate is 1 bad page per 100MB VRAM */ -#define TYPICAL_ECC_BAD_PAGE_RATE (100ULL * SZ_1M) - -#define COUNT_BAD_PAGE_THRESHOLD(size) (((size) >> 21) << 4) - /* Reserve 8 physical dram row for possible retirement. * In worst cases, it will lose 8 * 2MB memory in vram domain */ #define RAS_RESERVED_VRAM_SIZE_DEFAULT (16ULL << 20) - static void ras_mgr_init_event_mgr(struct ras_event_manager *mgr) { struct ras_event_state *event_state; @@ -114,73 +108,12 @@ static int amdgpu_ras_mgr_init_aca_config(struct amdgpu_device *adev, return 0; } -static uint64_t amdgpu_ras_mgr_reserved_vram_size(struct amdgpu_device *adev) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - uint64_t reserved_pages_in_bytes = 0; - - if (!con || (adev->flags & AMD_IS_APU)) - return 0; - - switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) { - case IP_VERSION(13, 0, 6): - case IP_VERSION(13, 0, 12): - reserved_pages_in_bytes = RAS_RESERVED_VRAM_SIZE_DEFAULT; - break; - case IP_VERSION(13, 0, 14): - reserved_pages_in_bytes = (RAS_RESERVED_VRAM_SIZE_DEFAULT << 1); - break; - default: - break; - } - return reserved_pages_in_bytes; -} - static int amdgpu_ras_mgr_init_eeprom_config(struct amdgpu_device *adev, struct ras_core_config *config) { struct ras_eeprom_config *eeprom_cfg = &config->eeprom_cfg; - uint64_t ras_reserved_vram_size; - ras_reserved_vram_size = amdgpu_ras_mgr_reserved_vram_size(adev); eeprom_cfg->eeprom_sys_fn = &amdgpu_ras_eeprom_i2c_sys_func; - eeprom_cfg->eeprom_i2c_adapter = adev->pm.ras_eeprom_i2c_bus; - if (eeprom_cfg->eeprom_i2c_adapter) { - const struct i2c_adapter_quirks *quirks = - ((struct i2c_adapter *)eeprom_cfg->eeprom_i2c_adapter)->quirks; - - if (quirks) { - eeprom_cfg->max_i2c_read_len = quirks->max_read_len; - eeprom_cfg->max_i2c_write_len = quirks->max_write_len; - } - } - - /* - * amdgpu_bad_page_threshold is used to config - * the threshold for the number of bad pages. - * -1: Threshold is set to default value - * Driver will issue a warning message when threshold is reached - * and continue runtime services. - * 0: Disable bad page retirement - * Driver will not retire bad pages - * which is intended for debugging purpose. - * -2: Threshold is determined by a formula - * that assumes 1 bad page per 100M of local memory. - * Driver will continue runtime services when threhold is reached. - * 0 < threshold < max number of bad page records in EEPROM, - * A user-defined threshold is set - * Driver will halt runtime services when this custom threshold is reached. - */ - if (amdgpu_bad_page_threshold == NONSTOP_OVER_THRESHOLD) - eeprom_cfg->eeprom_record_threshold_count = - div64_u64(adev->gmc.mc_vram_size, TYPICAL_ECC_BAD_PAGE_RATE); - else if (amdgpu_bad_page_threshold == WARN_NONSTOP_OVER_THRESHOLD) - eeprom_cfg->eeprom_record_threshold_count = - COUNT_BAD_PAGE_THRESHOLD(ras_reserved_vram_size); - else - eeprom_cfg->eeprom_record_threshold_count = amdgpu_bad_page_threshold; - - eeprom_cfg->eeprom_record_threshold_config = amdgpu_bad_page_threshold; return 0; } -- 2.55.0