[PATCH 048/109] drm/amd/ras: preload and handle bad pages at boot time
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> Preload bad pages occur during the sw_init stage, so the preload-related code in RAS module must be moved to sw_init for proper initialization. v2: Rename functions and variables. 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/core.c | 54 ++++++++++++++----- drivers/gpu/drm/amd/ras/core/eeprom.c | 27 ++++++---- drivers/gpu/drm/amd/ras/core/ras.h | 7 +++ drivers/gpu/drm/amd/ras/core/ras_mp1.c | 7 ++- drivers/gpu/drm/amd/ras/core/ras_mp1.h | 4 +- drivers/gpu/drm/amd/ras/core/ras_umc.c | 17 +++--- .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c | 25 +++++++++ .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h | 1 + .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c | 22 ++++++++ 9 files changed, 132 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/core.c b/drivers/gpu/drm/amd/ras/core/core.c index fc399192713ec..8a8f5134fdac7 100644 --- a/drivers/gpu/drm/amd/ras/core/core.c +++ b/drivers/gpu/drm/amd/ras/core/core.c @@ -331,6 +331,12 @@ int ras_core_sw_init(struct ras_core_context *ras_core) return -EINVAL; } + ras_core->ras_eeprom_supported = ras_core->config->ras_eeprom_supported; + ras_core->poison_supported = ras_core->config->poison_supported; + ras_core->early_init_service_enabled = ras_core->config->early_init_service_supported; + + ras_core->in_early_init = true; + ras_core->sys_fn = ras_core->config->sys_fn; if (!ras_core->sys_fn) return -EINVAL; @@ -367,6 +373,14 @@ int ras_core_sw_init(struct ras_core_context *ras_core) if (ret) return ret; + ret = ras_mp1_sw_init(ras_core); + if (ret) + return ret; + + ret = ras_eeprom_mgr_sw_init(ras_core); + if (ret) + return ret; + ret = ras_mce_sw_init(ras_core); if (ret) return ret; @@ -383,7 +397,9 @@ int ras_core_sw_fini(struct ras_core_context *ras_core) ras_log_ring_sw_fini(ras_core); ras_cmd_fini(ras_core); ras_umc_sw_fini(ras_core); + ras_mp1_sw_fini(ras_core); ras_aca_sw_fini(ras_core); + ras_eeprom_mgr_sw_fini(ras_core); ras_mce_sw_fini(ras_core); return 0; @@ -393,11 +409,6 @@ int ras_core_hw_init(struct ras_core_context *ras_core) { int ret; - ras_core->ras_eeprom_supported = - ras_core->config->ras_eeprom_supported; - - ras_core->poison_supported = ras_core->config->poison_supported; - ret = ras_psp_hw_init(ras_core); if (ret) return ret; @@ -406,10 +417,6 @@ int ras_core_hw_init(struct ras_core_context *ras_core) if (ret) goto init_err1; - ret = ras_mp1_hw_init(ras_core); - if (ret) - goto init_err2; - ret = ras_nbio_hw_init(ras_core); if (ret) goto init_err3; @@ -426,6 +433,8 @@ int ras_core_hw_init(struct ras_core_context *ras_core) if (ret) goto init_err6; + ras_core->in_early_init = false; + ret = ras_core_eeprom_recovery(ras_core); if (ret) { RAS_DEV_ERR(ras_core->dev, @@ -450,8 +459,6 @@ int ras_core_hw_init(struct ras_core_context *ras_core) init_err4: ras_nbio_hw_fini(ras_core); init_err3: - ras_mp1_hw_fini(ras_core); -init_err2: ras_aca_hw_fini(ras_core); init_err1: ras_psp_hw_fini(ras_core); @@ -467,7 +474,6 @@ int ras_core_hw_fini(struct ras_core_context *ras_core) ras_gfx_hw_fini(ras_core); ras_nbio_hw_fini(ras_core); ras_umc_hw_fini(ras_core); - ras_mp1_hw_fini(ras_core); ras_aca_hw_fini(ras_core); ras_psp_hw_fini(ras_core); @@ -782,3 +788,27 @@ bool ras_core_poison_supported(struct ras_core_context *ras_core) return ras_core->poison_supported ? true : ras_psp_poison_supported(ras_core); } + +bool ras_core_in_early_init(struct ras_core_context *ras_core) +{ + if (!ras_core) + return true; + + return ras_core->in_early_init; +} + +bool ras_core_early_init_service_enabled(struct ras_core_context *ras_core) +{ + return ras_core->early_init_service_enabled && + ras_eeprom_mgr_early_init_service_supported(ras_core); +} + +int ras_core_eeprom_early_init_service(struct ras_core_context *ras_core) +{ + if (!ras_core_early_init_service_enabled(ras_core)) + return -EOPNOTSUPP; + else if (!ras_core_in_early_init(ras_core)) + return -EACCES; + + return ras_core_eeprom_recovery(ras_core); +} diff --git a/drivers/gpu/drm/amd/ras/core/eeprom.c b/drivers/gpu/drm/amd/ras/core/eeprom.c index b261f11799f6c..01e4cde581f42 100644 --- a/drivers/gpu/drm/amd/ras/core/eeprom.c +++ b/drivers/gpu/drm/amd/ras/core/eeprom.c @@ -1085,7 +1085,7 @@ static int __read_table_ras_info(struct ras_eeprom_control *control) return res == RAS_TABLE_V2_1_INFO_SIZE ? 0 : res; } -static int __check_ras_table_status(struct ras_core_context *ras_core) +static int __ras_table_init(struct ras_core_context *ras_core) { struct ras_eeprom_control *control = ras_core->eeprom_mgr.ras_eeprom; unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 }; @@ -1102,7 +1102,6 @@ static int __check_ras_table_status(struct ras_core_context *ras_core) control->ras_header_offset = RAS_HDR_START; control->ras_info_offset = RAS_TABLE_V2_1_INFO_START; - mutex_init(&control->ras_tbl_mutex); /* Read the table header from EEPROM address */ res = __eeprom_read(ras_core, @@ -1284,18 +1283,26 @@ static int ras_eeprom_sw_init(struct ras_core_context *ras_core, control->i2c_adapter = param->eeprom_i2c_adapter; control->i2c_port = param->eeprom_i2c_port; control->i2c_address = param->eeprom_i2c_addr; + control->record_threshold_count = param->record_threshold; + control->sys_func = param->sys_fn; control->update_channel_flag = false; + mutex_init(&control->ras_tbl_mutex); + return 0; } static int ras_eeprom_sw_fini(struct ras_core_context *ras_core) { - if (!ras_core) + struct ras_eeprom_control *control = ras_core->eeprom_mgr.ras_eeprom; + + if (!control) return -EINVAL; - kfree(ras_core->eeprom_mgr.ras_eeprom); + mutex_destroy(&control->ras_tbl_mutex); + + kfree(control); ras_core->eeprom_mgr.ras_eeprom = NULL; return 0; @@ -1309,15 +1316,17 @@ static int ras_eeprom_hw_init(struct ras_core_context *ras_core, if (!control) return -EINVAL; - return __check_ras_table_status(ras_core); + control->max_read_len = param->max_i2c_read_len; + control->max_write_len = param->max_i2c_write_len; + control->i2c_adapter = param->eeprom_i2c_adapter; + control->i2c_port = param->eeprom_i2c_port; + control->i2c_address = param->eeprom_i2c_addr; + + return __ras_table_init(ras_core); } static int ras_eeprom_hw_fini(struct ras_core_context *ras_core) { - struct ras_eeprom_control *control = ras_core->eeprom_mgr.ras_eeprom; - - mutex_destroy(&control->ras_tbl_mutex); - return 0; } diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index a08f83ed05857..ba656c82d4ee6 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -153,6 +153,7 @@ enum ras_notify_event { RAS_EVENT_ID__RAS_EVENT_PROC_BEGIN, RAS_EVENT_ID__RAS_EVENT_PROC_END, RAS_EVENT_ID__UPDATE_ACA_DATA, + RAS_EVENT_ID__EARLY_INIT_RESERVE_PAGE, }; enum ras_gpu_status { @@ -359,6 +360,7 @@ struct ras_core_config { u32 nbio_ip_version; u32 psp_ip_version; + bool early_init_service_supported; bool poison_supported; bool ras_eeprom_supported; uint ras_debug_mask; @@ -402,6 +404,8 @@ struct ras_core_context { bool is_rma; bool is_initialized; + bool in_early_init; + bool early_init_service_enabled; struct kfifo de_seqno_fifo; struct kfifo consumption_seqno_fifo; @@ -474,4 +478,7 @@ int ras_core_get_ip_version(struct ras_core_context *ras_core, enum ras_unit_id unit_id, uint32_t *version); uint64_t ras_core_get_ras_caps(struct ras_core_context *ras_core); bool ras_core_poison_supported(struct ras_core_context *ras_core); +bool ras_core_in_early_init(struct ras_core_context *ras_core); +bool ras_core_early_init_service_enabled(struct ras_core_context *ras_core); +int ras_core_eeprom_early_init_service(struct ras_core_context *ras_core); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.c b/drivers/gpu/drm/amd/ras/core/ras_mp1.c index 7a2a6da26ae38..7ba872732efd2 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.c +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.c @@ -183,11 +183,14 @@ int ras_mp1_set_debug_mode(struct ras_core_context *ras_core, bool enable) return mp1->ip_func->set_debug_mode(ras_core, enable); } -int ras_mp1_hw_init(struct ras_core_context *ras_core) +int ras_mp1_sw_init(struct ras_core_context *ras_core) { struct ras_mp1 *mp1 = &ras_core->ras_mp1; int ret = 0; + if (!ras_core->config) + return -EINVAL; + mp1->mp1_ip_version = ras_core->config->mp1_ip_version; if (ras_core->config && ras_core->config->mp1_cfg.mp1_sys_fn) @@ -208,7 +211,7 @@ int ras_mp1_hw_init(struct ras_core_context *ras_core) return ret; } -int ras_mp1_hw_fini(struct ras_core_context *ras_core) +int ras_mp1_sw_fini(struct ras_core_context *ras_core) { struct ras_mp1 *mp1 = &ras_core->ras_mp1; diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.h b/drivers/gpu/drm/amd/ras/core/ras_mp1.h index 3b3d4cab1d0c9..6eac9488843e1 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.h +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.h @@ -88,8 +88,8 @@ struct ras_mp1 { struct mutex op_mutex; }; -int ras_mp1_hw_init(struct ras_core_context *ras_core); -int ras_mp1_hw_fini(struct ras_core_context *ras_core); +int ras_mp1_sw_init(struct ras_core_context *ras_core); +int ras_mp1_sw_fini(struct ras_core_context *ras_core); int ras_mp1_get_bank_count(struct ras_core_context *ras_core, enum ras_err_type type, u32 *count); diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c b/drivers/gpu/drm/amd/ras/core/ras_umc.c index b9961796a5395..ee4ad9ffb50c0 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_umc.c +++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c @@ -187,8 +187,9 @@ static void ras_umc_reserve_eeprom_record(struct ras_core_context *ras_core, /* Reserve memory */ for (i = 0; i < count; i++) - ras_core_event_notify(ras_core, - RAS_EVENT_ID__RESERVE_BAD_PAGE, &page_pfn[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]); } /* When gpu reset is ongoing, ecc logging operations will be pended. @@ -726,6 +727,13 @@ int ras_umc_sw_init(struct ras_core_context *ras_core) mutex_init(&ras_umc->umc_lock); mutex_init(&ras_umc->bank_log_lock); + ras_umc->umc_ip_version = ras_core->config->umc_ip_version; + ras_umc->ip_func = ras_umc_get_ip_func(ras_core, ras_umc->umc_ip_version); + if (!ras_umc->ip_func) { + RAS_DEV_ERR(ras_core->dev, "Failed to get umc ip function!\n"); + return -EINVAL; + } + return 0; } @@ -775,11 +783,6 @@ int ras_umc_hw_init(struct ras_core_context *ras_core) struct ras_umc *ras_umc = &ras_core->ras_umc; ras_umc->num_umc = ras_core->config->umc_cfg.num_umc; - ras_umc->umc_ip_version = ras_core->config->umc_ip_version; - ras_umc->ip_func = ras_umc_get_ip_func(ras_core, ras_umc->umc_ip_version); - if (!ras_umc->ip_func) - return -EINVAL; - return 0; } 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 d84cf9162e588..c08e573206bd2 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 @@ -257,6 +257,9 @@ static struct ras_core_context *amdgpu_ras_mgr_create_ras_core(struct amdgpu_dev init_config.umc_ip_version == IP_VERSION(12, 5, 0)) init_config.aca_ip_version = IP_VERSION(1, 0, 0); + if (init_config.mp1_ip_version == IP_VERSION(15, 0, 8)) + init_config.early_init_service_supported = true; + init_config.sys_fn = &amdgpu_ras_sys_fn; init_config.ras_eeprom_supported = amdgpu_ras_mgr_eeprom_is_supported(adev); @@ -738,3 +741,25 @@ bool amdgpu_ras_mgr_get_debug_mode(struct amdgpu_device *adev) return ras_mgr->is_debug_mode; } + +int amdgpu_ras_mgr_early_init_service(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct amdgpu_ras_mgr *ras_mgr; + int ret; + + if (!con->uniras_enabled) + return 0; + + ras_mgr = amdgpu_ras_mgr_get_context(adev); + if (!ras_mgr || !ras_mgr->ras_core) { + RAS_DEV_ERR(adev, "amdgpu ras sw is not ready!\n"); + return -EPERM; + } + + ret = ras_core_eeprom_early_init_service(ras_mgr->ras_core); + if (ret) + RAS_DEV_WARN(adev, "RAS early init service failure! ret:%d\n", ret); + + return ret; +} diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h index 056d482644984..cb98606306932 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h @@ -61,6 +61,7 @@ struct amdgpu_ras_mgr { extern const struct amdgpu_ip_block_version ras_v1_0_ip_block; +int amdgpu_ras_mgr_early_init_service(struct amdgpu_device *adev); struct amdgpu_ras_mgr *amdgpu_ras_mgr_get_context( struct amdgpu_device *adev); int amdgpu_enable_uniras(struct amdgpu_device *adev, bool enable); diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c index 4744a7991757b..6115f241f13b4 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c @@ -110,6 +110,25 @@ static int amdgpu_ras_sys_gen_seqno(struct ras_core_context *ras_core, } +static int amdgpu_ras_early_init_reserve_badpage(struct ras_core_context *ras_core, + uint64_t pfn) +{ + struct amdgpu_bo *bo; + void *va; + int ret; + + ret = amdgpu_bo_create_kernel_at(ras_core->dev, RAS_PFN_TO_ADDR(pfn), + AMDGPU_GPU_PAGE_SIZE, &bo, &va); + if (ret) { + ras_core->is_rma = true; + RAS_DEV_ERR(ras_core->dev, + "Early init: RAS failed to reserve: offset=0x%llx size=0x%x ret=%d\n", + RAS_PFN_TO_ADDR(pfn), AMDGPU_GPU_PAGE_SIZE, ret); + } + + return ret; +} + static int amdgpu_ras_sys_event_notifier(struct ras_core_context *ras_core, enum ras_notify_event event_id, void *data) { @@ -126,6 +145,9 @@ static int amdgpu_ras_sys_event_notifier(struct ras_core_context *ras_core, case RAS_EVENT_ID__RESERVE_BAD_PAGE: ret = amdgpu_ras_reserve_page(ras_core->dev, *(uint64_t *)data); break; + case RAS_EVENT_ID__EARLY_INIT_RESERVE_PAGE: + ret = amdgpu_ras_early_init_reserve_badpage(ras_core, *(uint64_t *)data); + break; case RAS_EVENT_ID__FATAL_ERROR_DETECTED: ret = amdgpu_ras_sys_detect_fatal_event(ras_core, data); break; -- 2.55.0