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

Reply via email to