[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.