krishnanadh / rpms / rasdaemon

Forked from rpms/rasdaemon a year ago
Clone
7fca25
commit 738bafafdcb2e8b0ced32fff31b13754d571090b
7fca25
Author: Jason Tian <jason@os.amperecomputing.com>
7fca25
Date:   Fri May 28 11:35:43 2021 +0800
7fca25
7fca25
    Add error handling for Ampere-specific errors.
7fca25
    
7fca25
    Save Ampere-specific errors' decode into sqlite3 data
7fca25
    base and log PCIe segment, bus/device/function number
7fca25
    into BMC SEL.
7fca25
    
7fca25
    Signed-off-by: Jason Tian <jason@os.amperecomputing.com>
7fca25
    Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
7fca25
7fca25
diff --git a/non-standard-ampere.c b/non-standard-ampere.c
7fca25
index 8cceb26..05b5252 100644
7fca25
--- a/non-standard-ampere.c
7fca25
+++ b/non-standard-ampere.c
7fca25
@@ -216,6 +216,13 @@ static const char * const err_bert_sub_type[] = {
7fca25
 	"PMPRO Fatal",
7fca25
 };
7fca25
 
7fca25
+static char *sqlite3_table_list[] = {
7fca25
+	"amp_payload0_event_tab",
7fca25
+	"amp_payload1_event_tab",
7fca25
+	"amp_payload2_event_tab",
7fca25
+	"amp_payload3_event_tab",
7fca25
+};
7fca25
+
7fca25
 struct amp_ras_type_info {
7fca25
 	int id;
7fca25
 	const char *name;
7fca25
@@ -352,6 +359,359 @@ static const char *oem_subtype_name(const struct amp_ras_type_info *info,
7fca25
 	return "unknown";
7fca25
 }
7fca25
 
7fca25
+#ifdef HAVE_SQLITE3
7fca25
+/*key pair definition for ampere specific error payload type 0*/
7fca25
+static const struct db_fields amp_payload0_event_fields[] = {
7fca25
+	{ .name = "id",			.type = "INTEGER PRIMARY KEY" },
7fca25
+	{ .name = "timestamp",          .type = "TEXT" },
7fca25
+	{ .name = "type",		.type = "TEXT" },
7fca25
+	{ .name = "subtype",		.type = "TEXT" },
7fca25
+	{ .name = "instance",		.type = "INTEGER" },
7fca25
+	{ .name = "socket_num",		.type = "INTEGER" },
7fca25
+	{ .name = "status_reg",		.type = "INTEGER" },
7fca25
+	{ .name = "addr_reg",		.type = "INTEGER" },
7fca25
+	{ .name = "misc0",		.type = "INTEGER" },
7fca25
+	{ .name = "misc1",		.type = "INTEGER" },
7fca25
+	{ .name = "misc2",		.type = "INTEGER" },
7fca25
+	{ .name = "misc3",		.type = "INTEGER" },
7fca25
+};
7fca25
+
7fca25
+static const struct db_table_descriptor amp_payload0_event_tab = {
7fca25
+	.name = "amp_payload0_event",
7fca25
+	.fields = amp_payload0_event_fields,
7fca25
+	.num_fields = ARRAY_SIZE(amp_payload0_event_fields),
7fca25
+};
7fca25
+
7fca25
+/*key pair definition for ampere specific error payload type 1*/
7fca25
+static const struct db_fields amp_payload1_event_fields[] = {
7fca25
+	{ .name = "id",			.type = "INTEGER PRIMARY KEY" },
7fca25
+	{ .name = "timestamp",          .type = "TEXT" },
7fca25
+	{ .name = "type",		.type = "TEXT" },
7fca25
+	{ .name = "subtype",		.type = "TEXT" },
7fca25
+	{ .name = "instance",		.type = "INTEGER" },
7fca25
+	{ .name = "socket_num",		.type = "INTEGER" },
7fca25
+	{ .name = "uncore_err_status",	.type = "INTEGER" },
7fca25
+	{ .name = "uncore_err_mask",	.type = "INTEGER" },
7fca25
+	{ .name = "uncore_err_sev",	.type = "INTEGER" },
7fca25
+	{ .name = "core_err_status",	.type = "INTEGER" },
7fca25
+	{ .name = "core_err_mask",	.type = "INTEGER" },
7fca25
+	{ .name = "root_err_cmd",	.type = "INTEGER" },
7fca25
+	{ .name = "root_err_status",	.type = "INTEGER" },
7fca25
+	{ .name = "src_id",		.type = "INTEGER" },
7fca25
+	{ .name = "reserved1",		.type = "INTEGER" },
7fca25
+	{ .name = "reserverd2",		.type = "INTEGER" },
7fca25
+};
7fca25
+
7fca25
+static const struct db_table_descriptor amp_payload1_event_tab = {
7fca25
+	.name = "amp_payload1_event",
7fca25
+	.fields = amp_payload1_event_fields,
7fca25
+	.num_fields = ARRAY_SIZE(amp_payload1_event_fields),
7fca25
+};
7fca25
+
7fca25
+/*key pair definition for ampere specific error payload type 2*/
7fca25
+static const struct db_fields amp_payload2_event_fields[] = {
7fca25
+	{ .name = "id",                 .type = "INTEGER PRIMARY KEY" },
7fca25
+	{ .name = "timestamp",          .type = "TEXT" },
7fca25
+	{ .name = "type",		.type = "TEXT" },
7fca25
+	{ .name = "subtype",		.type = "TEXT" },
7fca25
+	{ .name = "instance",		.type = "INTEGER" },
7fca25
+	{ .name = "socket_num",		.type = "INTEGER" },
7fca25
+	{ .name = "ce_report_reg",	.type = "INTEGER" },
7fca25
+	{ .name = "ce_location",	.type = "INTEGER" },
7fca25
+	{ .name = "ce_addr",		.type = "INTEGER" },
7fca25
+	{ .name = "ue_report_reg",	.type = "INTEGER" },
7fca25
+	{ .name = "ue_location",	.type = "INTEGER" },
7fca25
+	{ .name = "ue_addr",		.type = "INTEGER" },
7fca25
+	{ .name = "reserved1",		.type = "INTEGER" },
7fca25
+	{ .name = "reserved2",		.type = "INTEGER" },
7fca25
+	{ .name = "reserved2",		.type = "INTEGER" },
7fca25
+};
7fca25
+
7fca25
+static const struct db_table_descriptor amp_payload2_event_tab = {
7fca25
+	.name = "amp_payload2_event",
7fca25
+	.fields = amp_payload2_event_fields,
7fca25
+	.num_fields = ARRAY_SIZE(amp_payload2_event_fields),
7fca25
+};
7fca25
+
7fca25
+/*key pair definition for ampere specific error payload type 3*/
7fca25
+static const struct db_fields amp_payload3_event_fields[] = {
7fca25
+	{ .name = "id",                 .type = "INTEGER PRIMARY KEY" },
7fca25
+	{ .name = "timestamp",          .type = "TEXT" },
7fca25
+	{ .name = "type",		.type = "TEXT" },
7fca25
+	{ .name = "subtype",		.type = "TEXT" },
7fca25
+	{ .name = "instance",		.type = "INTEGER" },
7fca25
+	{ .name = "socket_num",		.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data0",	.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data1",	.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data2",	.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data3",	.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data4",	.type = "INTEGER" },
7fca25
+	{ .name = "fw_spec_data5",	.type = "INTEGER" },
7fca25
+};
7fca25
+
7fca25
+static const struct db_table_descriptor amp_payload3_event_tab = {
7fca25
+	.name = "amp_payload3_event",
7fca25
+	.fields = amp_payload3_event_fields,
7fca25
+	.num_fields = ARRAY_SIZE(amp_payload3_event_fields),
7fca25
+};
7fca25
+
7fca25
+/*Save data with different type into sqlite3 db*/
7fca25
+static void record_amp_data(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+			    enum amp_oem_data_type data_type,
7fca25
+			    int id, int64_t data, const char *text)
7fca25
+{
7fca25
+	switch (data_type) {
7fca25
+	case AMP_OEM_DATA_TYPE_INT:
7fca25
+		sqlite3_bind_int(ev_decoder->stmt_dec_record, id, data);
7fca25
+		break;
7fca25
+	case AMP_OEM_DATA_TYPE_INT64:
7fca25
+		sqlite3_bind_int64(ev_decoder->stmt_dec_record, id, data);
7fca25
+		break;
7fca25
+	case AMP_OEM_DATA_TYPE_TEXT:
7fca25
+		sqlite3_bind_text(ev_decoder->stmt_dec_record, id,
7fca25
+				  text, -1, NULL);
7fca25
+		break;
7fca25
+	default:
7fca25
+		break;
7fca25
+	}
7fca25
+}
7fca25
+
7fca25
+static int store_amp_err_data(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *name)
7fca25
+{
7fca25
+	int rc;
7fca25
+
7fca25
+	rc = sqlite3_step(ev_decoder->stmt_dec_record);
7fca25
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
7fca25
+		log(TERM, LOG_ERR,
7fca25
+		    "Failed to do %s step on sqlite: error = %d\n", name, rc);
7fca25
+
7fca25
+	rc = sqlite3_reset(ev_decoder->stmt_dec_record);
7fca25
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
7fca25
+		log(TERM, LOG_ERR,
7fca25
+		    "Failed to reset %s on sqlite: error = %d\n", name, rc);
7fca25
+
7fca25
+	rc = sqlite3_clear_bindings(ev_decoder->stmt_dec_record);
7fca25
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
7fca25
+		log(TERM, LOG_ERR,
7fca25
+		    "Failed to clear bindings %s on sqlite: error = %d\n",
7fca25
+		    name, rc);
7fca25
+
7fca25
+	return rc;
7fca25
+}
7fca25
+
7fca25
+/*save all Ampere Specific Error Payload type 0 to sqlite3 database*/
7fca25
+static void record_amp_payload0_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload0_type_sec *err)
7fca25
+{
7fca25
+	if (ev_decoder != NULL) {
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD0_FIELD_TYPE, 0, type_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD0_FIELD_SUB_TYPE, 0, subtype_str);
7fca25
+
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD0_FIELD_INS, INSTANCE(err->instance), NULL);
7fca25
+
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD0_FIELD_SOCKET_NUM,
7fca25
+			SOCKET_NUM(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD0_FIELD_STATUS_REG, err->err_status, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD0_FIELD_ADDR_REG,
7fca25
+			err->err_addr, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD0_FIELD_MISC0,
7fca25
+			err->err_misc_0, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD0_FIELD_MISC1,
7fca25
+			err->err_misc_1, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD0_FIELD_MISC2,
7fca25
+			err->err_misc_2, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD0_FIELD_MISC3,
7fca25
+			err->err_misc_3, NULL);
7fca25
+		store_amp_err_data(ev_decoder, "amp_payload0_event_tab");
7fca25
+	}
7fca25
+}
7fca25
+
7fca25
+/*save all Ampere Specific Error Payload type 1 to sqlite3 database*/
7fca25
+static void record_amp_payload1_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload1_type_sec *err)
7fca25
+{
7fca25
+	if (ev_decoder != NULL) {
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+				AMP_PAYLOAD1_FIELD_TYPE, 0, type_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+				AMP_PAYLOAD1_FIELD_SUB_TYPE, 0, subtype_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_INS,
7fca25
+				INSTANCE(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_SOCKET_NUM,
7fca25
+				SOCKET_NUM(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_UNCORE_ERR_STATUS,
7fca25
+				err->uncore_status, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_UNCORE_ERR_MASK,
7fca25
+				err->uncore_mask, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_UNCORE_ERR_SEV,
7fca25
+				err->uncore_sev, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_CORE_ERR_STATUS,
7fca25
+				err->core_status, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_CORE_ERR_MASK,
7fca25
+				err->core_mask, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_ROOT_ERR_CMD,
7fca25
+				err->root_err_cmd, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_ROOT_ERR_STATUS,
7fca25
+				err->root_status, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_SRC_ID,
7fca25
+				err->src_id, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+				AMP_PAYLOAD1_FIELD_RESERVED1,
7fca25
+				err->reserved1, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+				AMP_PAYLOAD1_FIELD_RESERVED2,
7fca25
+				err->reserved2, NULL);
7fca25
+		store_amp_err_data(ev_decoder, "amp_payload1_event_tab");
7fca25
+	}
7fca25
+}
7fca25
+
7fca25
+/*save all Ampere Specific Error Payload type 2 to sqlite3 database*/
7fca25
+static void record_amp_payload2_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload2_type_sec *err)
7fca25
+{
7fca25
+	if (ev_decoder != NULL) {
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD2_FIELD_TYPE, 0, type_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD2_FIELD_SUB_TYPE, 0, subtype_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_INS, INSTANCE(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_SOCKET_NUM,
7fca25
+			SOCKET_NUM(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_CE_REPORT_REG,
7fca25
+			err->ce_register, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_CE_LOACATION,
7fca25
+			err->ce_location, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_CE_ADDR,
7fca25
+			err->ce_addr, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_UE_REPORT_REG,
7fca25
+			err->ue_register, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_UE_LOCATION,
7fca25
+			err->ue_location, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_UE_ADDR,
7fca25
+			err->ue_addr, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD2_FIELD_RESERVED1,
7fca25
+			err->reserved1, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD2_FIELD_RESERVED2,
7fca25
+			err->reserved2, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD2_FIELD_RESERVED3,
7fca25
+			err->reserved3, NULL);
7fca25
+		store_amp_err_data(ev_decoder, "amp_payload2_event_tab");
7fca25
+	}
7fca25
+}
7fca25
+
7fca25
+/*save all Ampere Specific Error Payload type 3 to sqlite3 database*/
7fca25
+static void record_amp_payload3_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload3_type_sec *err)
7fca25
+{
7fca25
+	if (ev_decoder != NULL) {
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD3_FIELD_TYPE, 0, type_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			AMP_PAYLOAD3_FIELD_SUB_TYPE, 0, subtype_str);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD3_FIELD_INS, INSTANCE(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD3_FIELD_SOCKET_NUM,
7fca25
+			SOCKET_NUM(err->instance), NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA0,
7fca25
+			err->fw_speci_data0, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA1,
7fca25
+			err->fw_speci_data1, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA2,
7fca25
+			err->fw_speci_data2, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA3,
7fca25
+			err->fw_speci_data3, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA4,
7fca25
+			err->fw_speci_data4, NULL);
7fca25
+		record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_INT64,
7fca25
+			AMP_PAYLOAD3_FIELD_FW_SPEC_DATA5,
7fca25
+			err->fw_speci_data5, NULL);
7fca25
+		store_amp_err_data(ev_decoder, "amp_payload3_event_tab");
7fca25
+	}
7fca25
+}
7fca25
+
7fca25
+#else
7fca25
+static void record_amp_data(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+			    enum amp_oem_data_type data_type,
7fca25
+			    int id, int64_t data, const char *text)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+
7fca25
+static void record_amp_payload0_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload0_type_sec *err)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+
7fca25
+static void record_amp_payload1_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload1_type_sec *err)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+
7fca25
+static void record_amp_payload2_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload2_type_sec *err)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+
7fca25
+static void record_amp_payload3_err(struct ras_ns_ev_decoder *ev_decoder,
7fca25
+				const char *type_str, const char *subtype_str,
7fca25
+				const struct amp_payload3_type_sec *err)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+
7fca25
+static int store_amp_err_data(struct ras_ns_ev_decoder *ev_decoder, char *name)
7fca25
+{
7fca25
+	return 0;
7fca25
+}
7fca25
+#endif
7fca25
 
7fca25
 /*decode ampere specific error payload type 0, the CPU's data is save*/
7fca25
 /*to sqlite by ras-arm-handler, others are saved by this function.*/
7fca25
@@ -434,6 +794,7 @@ void decode_amp_payload0_err_regs(struct ras_ns_ev_decoder *ev_decoder,
7fca25
 		*p = '\0';
7fca25
 	}
7fca25
 
7fca25
+	record_amp_payload0_err(ev_decoder, type_str, subtype_str, err);
7fca25
 	i = 0;
7fca25
 	p = NULL;
7fca25
 	end = NULL;
7fca25
@@ -517,6 +878,7 @@ static void decode_amp_payload1_err_regs(struct ras_ns_ev_decoder *ev_decoder,
7fca25
 		*p = '\0';
7fca25
 	}
7fca25
 
7fca25
+	record_amp_payload1_err(ev_decoder, type_str, subtype_str, err);
7fca25
 	i = 0;
7fca25
 	p = NULL;
7fca25
 	end = NULL;
7fca25
@@ -601,6 +963,7 @@ static void decode_amp_payload2_err_regs(struct ras_ns_ev_decoder *ev_decoder,
7fca25
 		*p = '\0';
7fca25
 	}
7fca25
 
7fca25
+	record_amp_payload2_err(ev_decoder, type_str, subtype_str, err);
7fca25
 	i = 0;
7fca25
 	p = NULL;
7fca25
 	end = NULL;
7fca25
@@ -673,6 +1036,7 @@ static void decode_amp_payload3_err_regs(struct ras_ns_ev_decoder *ev_decoder,
7fca25
 		*p = '\0';
7fca25
 	}
7fca25
 
7fca25
+	record_amp_payload3_err(ev_decoder, type_str, subtype_str, err);
7fca25
 	i = 0;
7fca25
 	p = NULL;
7fca25
 	end = NULL;
7fca25
@@ -687,6 +1051,38 @@ static int decode_amp_oem_type_error(struct ras_events *ras,
7fca25
 {
7fca25
 	int payload_type = PAYLOAD_TYPE(event->error[0]);
7fca25
 
7fca25
+#ifdef HAVE_SQLITE3
7fca25
+	struct db_table_descriptor db_tab;
7fca25
+	int id = 0;
7fca25
+
7fca25
+	if (payload_type == PAYLOAD_TYPE_0) {
7fca25
+		db_tab = amp_payload0_event_tab;
7fca25
+		id = AMP_PAYLOAD0_FIELD_TIMESTAMP;
7fca25
+	} else if (payload_type == PAYLOAD_TYPE_1) {
7fca25
+		db_tab = amp_payload1_event_tab;
7fca25
+		id = AMP_PAYLOAD1_FIELD_TIMESTAMP;
7fca25
+	} else if (payload_type == PAYLOAD_TYPE_2) {
7fca25
+		db_tab = amp_payload2_event_tab;
7fca25
+		id = AMP_PAYLOAD2_FIELD_TIMESTAMP;
7fca25
+	} else if (payload_type == PAYLOAD_TYPE_3) {
7fca25
+		db_tab = amp_payload3_event_tab;
7fca25
+		id = AMP_PAYLOAD3_FIELD_TIMESTAMP;
7fca25
+	} else
7fca25
+		return -1;
7fca25
+
7fca25
+	if (!ev_decoder->stmt_dec_record) {
7fca25
+		if (ras_mc_add_vendor_table(ras, &ev_decoder->stmt_dec_record,
7fca25
+					    &db_tab) != SQLITE_OK) {
7fca25
+			trace_seq_printf(s,
7fca25
+					"create sql %s fail\n",
7fca25
+					sqlite3_table_list[payload_type]);
7fca25
+			return -1;
7fca25
+		}
7fca25
+	}
7fca25
+	record_amp_data(ev_decoder, AMP_OEM_DATA_TYPE_TEXT,
7fca25
+			   id, 0, event->timestamp);
7fca25
+#endif
7fca25
+
7fca25
 	if (payload_type == PAYLOAD_TYPE_0) {
7fca25
 		const struct amp_payload0_type_sec *err =
7fca25
 			(struct amp_payload0_type_sec *)event->error;
7fca25
diff --git a/non-standard-ampere.h b/non-standard-ampere.h
7fca25
index aacf3a8..f463c53 100644
7fca25
--- a/non-standard-ampere.h
7fca25
+++ b/non-standard-ampere.h
7fca25
@@ -102,6 +102,79 @@ struct amp_payload3_type_sec {
7fca25
 	uint64_t   fw_speci_data5;
7fca25
 };
7fca25
 
7fca25
+enum amp_oem_data_type {
7fca25
+	AMP_OEM_DATA_TYPE_INT,
7fca25
+	AMP_OEM_DATA_TYPE_INT64,
7fca25
+	AMP_OEM_DATA_TYPE_TEXT,
7fca25
+};
7fca25
+
7fca25
+enum {
7fca25
+	AMP_PAYLOAD0_FIELD_ID,
7fca25
+	AMP_PAYLOAD0_FIELD_TIMESTAMP,
7fca25
+	AMP_PAYLOAD0_FIELD_TYPE,
7fca25
+	AMP_PAYLOAD0_FIELD_SUB_TYPE,
7fca25
+	AMP_PAYLOAD0_FIELD_INS,
7fca25
+	AMP_PAYLOAD0_FIELD_SOCKET_NUM,
7fca25
+	AMP_PAYLOAD0_FIELD_STATUS_REG,
7fca25
+	AMP_PAYLOAD0_FIELD_ADDR_REG,
7fca25
+	AMP_PAYLOAD0_FIELD_MISC0,
7fca25
+	AMP_PAYLOAD0_FIELD_MISC1,
7fca25
+	AMP_PAYLOAD0_FIELD_MISC2,
7fca25
+	AMP_PAYLOAD0_FIELD_MISC3,
7fca25
+};
7fca25
+
7fca25
+enum {
7fca25
+	AMP_PAYLOAD1_FIELD_ID,
7fca25
+	AMP_PAYLOAD1_FIELD_TIMESTAMP,
7fca25
+	AMP_PAYLOAD1_FIELD_TYPE,
7fca25
+	AMP_PAYLOAD1_FIELD_SUB_TYPE,
7fca25
+	AMP_PAYLOAD1_FIELD_INS,
7fca25
+	AMP_PAYLOAD1_FIELD_SOCKET_NUM,
7fca25
+	AMP_PAYLOAD1_FIELD_UNCORE_ERR_STATUS,
7fca25
+	AMP_PAYLOAD1_FIELD_UNCORE_ERR_MASK,
7fca25
+	AMP_PAYLOAD1_FIELD_UNCORE_ERR_SEV,
7fca25
+	AMP_PAYLOAD1_FIELD_CORE_ERR_STATUS,
7fca25
+	AMP_PAYLOAD1_FIELD_CORE_ERR_MASK,
7fca25
+	AMP_PAYLOAD1_FIELD_ROOT_ERR_CMD,
7fca25
+	AMP_PAYLOAD1_FIELD_ROOT_ERR_STATUS,
7fca25
+	AMP_PAYLOAD1_FIELD_SRC_ID,
7fca25
+	AMP_PAYLOAD1_FIELD_RESERVED1,
7fca25
+	AMP_PAYLOAD1_FIELD_RESERVED2,
7fca25
+};
7fca25
+
7fca25
+enum {
7fca25
+	AMP_PAYLOAD2_FIELD_ID,
7fca25
+	AMP_PAYLOAD2_FIELD_TIMESTAMP,
7fca25
+	AMP_PAYLOAD2_FIELD_TYPE,
7fca25
+	AMP_PAYLOAD2_FIELD_SUB_TYPE,
7fca25
+	AMP_PAYLOAD2_FIELD_INS,
7fca25
+	AMP_PAYLOAD2_FIELD_SOCKET_NUM,
7fca25
+	AMP_PAYLOAD2_FIELD_CE_REPORT_REG,
7fca25
+	AMP_PAYLOAD2_FIELD_CE_LOACATION,
7fca25
+	AMP_PAYLOAD2_FIELD_CE_ADDR,
7fca25
+	AMP_PAYLOAD2_FIELD_UE_REPORT_REG,
7fca25
+	AMP_PAYLOAD2_FIELD_UE_LOCATION,
7fca25
+	AMP_PAYLOAD2_FIELD_UE_ADDR,
7fca25
+	AMP_PAYLOAD2_FIELD_RESERVED1,
7fca25
+	AMP_PAYLOAD2_FIELD_RESERVED2,
7fca25
+	AMP_PAYLOAD2_FIELD_RESERVED3,
7fca25
+};
7fca25
+
7fca25
+enum {
7fca25
+	AMP_PAYLOAD3_FIELD_ID,
7fca25
+	AMP_PAYLOAD3_FIELD_TIMESTAMP,
7fca25
+	AMP_PAYLOAD3_FIELD_TYPE,
7fca25
+	AMP_PAYLOAD3_FIELD_SUB_TYPE,
7fca25
+	AMP_PAYLOAD3_FIELD_INS,
7fca25
+	AMP_PAYLOAD3_FIELD_SOCKET_NUM,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA0,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA1,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA2,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA3,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA4,
7fca25
+	AMP_PAYLOAD3_FIELD_FW_SPEC_DATA5
7fca25
+};
7fca25
+
7fca25
 void decode_amp_payload0_err_regs(struct ras_ns_ev_decoder *ev_decoder,
7fca25
 				  struct trace_seq *s,
7fca25
 				  const struct amp_payload0_type_sec *err);
7fca25
diff --git a/ras-aer-handler.c b/ras-aer-handler.c
7fca25
index 8ddd439..6f4cb2b 100644
7fca25
--- a/ras-aer-handler.c
7fca25
+++ b/ras-aer-handler.c
7fca25
@@ -67,6 +67,9 @@ int ras_aer_event_handler(struct trace_seq *s,
7fca25
 	struct tm *tm;
7fca25
 	struct ras_aer_event ev;
7fca25
 	char buf[BUF_LEN];
7fca25
+	char ipmi_add_sel[105];
7fca25
+	uint8_t sel_data[5];
7fca25
+	int seg, bus, dev, fn;
7fca25
 
7fca25
 	/*
7fca25
 	 * Newer kernels (3.10-rc1 or upper) provide an uptime clock.
7fca25
@@ -129,15 +132,19 @@ int ras_aer_event_handler(struct trace_seq *s,
7fca25
 	switch (severity_val) {
7fca25
 	case HW_EVENT_AER_UNCORRECTED_NON_FATAL:
7fca25
 		ev.error_type = "Uncorrected (Non-Fatal)";
7fca25
+		sel_data[0] = 0xca;
7fca25
 		break;
7fca25
 	case HW_EVENT_AER_UNCORRECTED_FATAL:
7fca25
 		ev.error_type = "Uncorrected (Fatal)";
7fca25
+		sel_data[0] = 0xca;
7fca25
 		break;
7fca25
 	case HW_EVENT_AER_CORRECTED:
7fca25
 		ev.error_type = "Corrected";
7fca25
+		sel_data[0] = 0xbf;
7fca25
 		break;
7fca25
 	default:
7fca25
 		ev.error_type = "Unknown severity";
7fca25
+		sel_data[0] = 0xbf;
7fca25
 	}
7fca25
 	trace_seq_puts(s, ev.error_type);
7fca25
 
7fca25
@@ -151,5 +158,29 @@ int ras_aer_event_handler(struct trace_seq *s,
7fca25
 	ras_report_aer_event(ras, &ev;;
7fca25
 #endif
7fca25
 
7fca25
+#ifdef HAVE_AMP_NS_DECODE
7fca25
+	/*
7fca25
+	 * Get PCIe AER error source seg/bus/dev/fn and save it into
7fca25
+	 * BMC OEM SEL, ipmitool raw 0x0a 0x44 is IPMI command-Add SEL
7fca25
+	 * entry, please refer IPMI specificaiton chapter 31.6. 0xcd3a
7fca25
+	 * is manufactuer ID(ampere),byte 12 is sensor num(CE is 0xBF,
7fca25
+	 * UE is 0xCA), byte 13~14 is segment number, byte 15 is bus
7fca25
+	 * number, byte 16[7:3] is device number, byte 16[2:0] is
7fca25
+	 * function number
7fca25
+	 */
7fca25
+	sscanf(ev.dev_name, "%x:%x:%x.%x", &seg, &bus, &dev, &fn);
7fca25
+
7fca25
+	sel_data[1] = seg & 0xff;
7fca25
+	sel_data[2] = (seg & 0xff00) >> 8;
7fca25
+	sel_data[3] = bus;
7fca25
+	sel_data[4] = (((dev & 0x1f) << 3) | (fn & 0x7));
7fca25
+
7fca25
+	sprintf(ipmi_add_sel,
7fca25
+	  "ipmitool raw 0x0a 0x44 0x00 0x00 0xc0 0x00 0x00 0x00 0x00 0x3a 0xcd 0x00 0xc0 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
7fca25
+	  sel_data[0], sel_data[1], sel_data[2], sel_data[3], sel_data[4]);
7fca25
+
7fca25
+	system(ipmi_add_sel);
7fca25
+#endif
7fca25
+
7fca25
 	return 0;
7fca25
 }