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