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

Reply via email to