[PATCH 039/109] drm/amd/ras: ras mp1 introduces common interfaces
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> Ras mp1 introduces common interfaces to manage mp1 data obtained from different ASICs. v2: Add mutex to ensure complete data transactions with MP1. 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/ras_mp1.c | 122 ++++++++++++++++++++++++- drivers/gpu/drm/amd/ras/core/ras_mp1.h | 44 +++++++++ 2 files changed, 161 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.c b/drivers/gpu/drm/amd/ras/core/ras_mp1.c index 12c9e20098c43..eccd6f16c35a7 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.c +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.c @@ -50,23 +50,127 @@ int ras_mp1_get_bank_count(struct ras_core_context *ras_core, enum ras_err_type type, u32 *count) { struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; if (!mp1->ip_func || !mp1->ip_func->get_valid_bank_count) return 0; - return mp1->ip_func->get_valid_bank_count(ras_core, type, count); + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->get_valid_bank_count(ras_core, type, count); + mutex_unlock(&mp1->op_mutex); + + return ret; } int ras_mp1_dump_bank(struct ras_core_context *ras_core, u32 type, u32 idx, u64 *regs, u32 regs_sz) { struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; if (!mp1->ip_func || !mp1->ip_func->dump_valid_bank) return 0; - return mp1->ip_func->dump_valid_bank(ras_core, + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->dump_valid_bank(ras_core, type, idx, regs, regs_sz); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +int ras_mp1_get_table_version(struct ras_core_context *ras_core, + u32 *table_version) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!mp1->ip_func || !mp1->ip_func->get_table_version) + return -EOPNOTSUPP; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->get_table_version(ras_core, table_version); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +bool ras_mp1_rma_detected(struct ras_core_context *ras_core) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!mp1->ip_func || !mp1->ip_func->rma_detected) + return false; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->rma_detected(ras_core); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +int ras_mp1_set_timestamp(struct ras_core_context *ras_core, + u32 timestamp) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!mp1->ip_func || !mp1->ip_func->set_timestamp) + return -EOPNOTSUPP; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->set_timestamp(ras_core, timestamp); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +int ras_mp1_reset_ras_table(struct ras_core_context *ras_core, + u32 *result) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!result || !mp1->ip_func || !mp1->ip_func->reset_ras_table) + return -EOPNOTSUPP; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->reset_ras_table(ras_core, result); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +int ras_mp1_get_record_count(struct ras_core_context *ras_core, u32 *count) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!count || !mp1->ip_func || !mp1->ip_func->get_record_count) + return 0; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->get_record_count(ras_core, count); + mutex_unlock(&mp1->op_mutex); + + return ret; +} + +int ras_mp1_get_record(struct ras_core_context *ras_core, + u32 idx, struct eeprom_err_record *rec) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + int ret; + + if (!rec || !mp1->ip_func || !mp1->ip_func->get_record) + return -EOPNOTSUPP; + + mutex_lock(&mp1->op_mutex); + ret = mp1->ip_func->get_record(ras_core, idx, rec); + mutex_unlock(&mp1->op_mutex); + + return ret; } int ras_mp1_set_debug_mode(struct ras_core_context *ras_core, bool enable) @@ -86,21 +190,29 @@ int ras_mp1_hw_init(struct ras_core_context *ras_core) mp1->mp1_ip_version = ras_core->config->mp1_ip_version; - if (ras_core->config->mp1_cfg.mp1_sys_fn) + if (ras_core->config && ras_core->config->mp1_cfg.mp1_sys_fn) mp1->sys_func = ras_core->config->mp1_cfg.mp1_sys_fn; mp1->ip_func = ras_mp1_get_ip_funcs(ras_core, mp1->mp1_ip_version); if (!mp1->ip_func) return -EINVAL; + mutex_init(&mp1->op_mutex); + ret = ras_mp1_set_debug_mode(ras_core, false); - if (ret) - return -EINVAL; + if (ret) { + mutex_destroy(&mp1->op_mutex); + return ret; + } return ret; } int ras_mp1_hw_fini(struct ras_core_context *ras_core) { + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + + mutex_destroy(&mp1->op_mutex); + return 0; } diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.h b/drivers/gpu/drm/amd/ras/core/ras_mp1.h index 17499e1c9c54b..a00eb8117885b 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.h +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.h @@ -25,6 +25,26 @@ #define __RAS_MP1_H__ #include "ras.h" +struct eeprom_err_record { + u32 timestamp; + + union { + struct { + u32 mca_addr_low; + u32 mca_addr_high; + }; + u64 mca_addr; + }; + + union { + struct { + u32 ipid_low; + u32 ipid_high; + }; + u64 ipid; + }; +}; + enum ras_err_type; struct ras_mp1_ip_func { int (*get_valid_bank_count)(struct ras_core_context *ras_core, @@ -32,12 +52,26 @@ struct ras_mp1_ip_func { int (*dump_valid_bank)(struct ras_core_context *ras_core, enum ras_err_type type, u32 idx, u64 *regs, u32 regs_sz); int (*set_debug_mode)(struct ras_core_context *ras_core, bool enable); + + /* The following is used for firmware management of EEPROM */ + int (*get_table_version)(struct ras_core_context *ras_core, + u32 *table_version); + bool (*rma_detected)(struct ras_core_context *ras_core); + int (*set_timestamp)(struct ras_core_context *ras_core, + u32 timestamp); + int (*reset_ras_table)(struct ras_core_context *ras_core, + u32 *result); + int (*get_record_count)(struct ras_core_context *ras_core, + u32 *count); + int (*get_record)(struct ras_core_context *ras_core, + u32 idx, struct eeprom_err_record *rec); }; struct ras_mp1 { uint32_t mp1_ip_version; const struct ras_mp1_ip_func *ip_func; const struct ras_mp1_sys_func *sys_func; + struct mutex op_mutex; }; int ras_mp1_hw_init(struct ras_core_context *ras_core); @@ -50,4 +84,14 @@ int ras_mp1_dump_bank(struct ras_core_context *ras_core, u32 ecc_type, u32 idx, u64 *regs, u32 regs_sz); int ras_mp1_set_debug_mode(struct ras_core_context *ras_core, bool enable); +int ras_mp1_get_table_version(struct ras_core_context *ras_core, + u32 *table_version); +bool ras_mp1_rma_detected(struct ras_core_context *ras_core); +int ras_mp1_set_timestamp(struct ras_core_context *ras_core, + u32 timestamp); +int ras_mp1_reset_ras_table(struct ras_core_context *ras_core, + u32 *result); +int ras_mp1_get_record_count(struct ras_core_context *ras_core, u32 *count); +int ras_mp1_get_record(struct ras_core_context *ras_core, + u32 idx, struct eeprom_err_record *rec); #endif -- 2.55.0