[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,
+				&param_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
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.