[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
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.