summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/ipmi/ocp/Makefile.inc2
-rw-r--r--src/drivers/ipmi/ocp/ipmi_ocp.h26
-rw-r--r--src/drivers/ocp/ewl/ewl.c31
3 files changed, 58 insertions, 1 deletions
diff --git a/src/drivers/ipmi/ocp/Makefile.inc b/src/drivers/ipmi/ocp/Makefile.inc
index 2b492e124d..3d5e69eb12 100644
--- a/src/drivers/ipmi/ocp/Makefile.inc
+++ b/src/drivers/ipmi/ocp/Makefile.inc
@@ -1,5 +1,5 @@
ramstage-$(CONFIG_IPMI_OCP) += ipmi_ocp.c ipmi_sel.c
ifeq ($(CONFIG_IPMI_OCP),y)
-romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_ocp_romstage.c
+romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_ocp_romstage.c ipmi_sel.c
smm-$(CONFIG_IPMI_BMC_SEL) += ipmi_sel.c
endif
diff --git a/src/drivers/ipmi/ocp/ipmi_ocp.h b/src/drivers/ipmi/ocp/ipmi_ocp.h
index 571eafc731..d02eb35449 100644
--- a/src/drivers/ipmi/ocp/ipmi_ocp.h
+++ b/src/drivers/ipmi/ocp/ipmi_ocp.h
@@ -89,6 +89,16 @@ enum fail_type {
PCIE_ECRC_EVNT = 5,
};
+enum sel_err_type {
+ MEM_TRAINING_ERR = 0,
+ MEM_CORR_ERR = 1,
+ MEM_UNCORR_ERR = 2,
+ MEM_CORR_ERR_PATROL = 3,
+ MEM_UNCORR_ERR_PATROL = 4,
+ MEM_PARITY_ERR = 5,
+ MEM_UNDEFINED = 0xF,
+};
+
struct ipmi_sel_pcie_dev_fail {
uint16_t record_id;
uint8_t record_type;
@@ -102,6 +112,21 @@ struct ipmi_sel_pcie_dev_fail {
uint8_t rsvd2;
} __packed;
+struct ipmi_sel_mem_err {
+ uint16_t record_id;
+ uint8_t record_type;
+ uint8_t general_info;
+ uint32_t timestamp;
+ uint8_t socket;
+ uint8_t channel;
+ uint8_t dimm_slot;
+ uint8_t rsvd1;
+ uint8_t dimm_failure_type;
+ uint8_t major_code;
+ uint8_t minor_code;
+ uint8_t rsvd2;
+} __packed;
+
struct ipmi_config_rsp {
uint8_t board_sku_id;
uint8_t board_rev_id;
@@ -111,6 +136,7 @@ struct ipmi_config_rsp {
#define SEL_RECORD_ID 0x01
#define SEL_PCIE_DEV_ERR 0x20
+#define SEL_INTEL_MEMORY_ERROR 0x21
#define SEL_PCIE_IIO_ERR 0x23
#define SEL_PCIE_DEV_FAIL_ID 0x29
diff --git a/src/drivers/ocp/ewl/ewl.c b/src/drivers/ocp/ewl/ewl.c
index 871981a28b..244634bcf9 100644
--- a/src/drivers/ocp/ewl/ewl.c
+++ b/src/drivers/ocp/ewl/ewl.c
@@ -2,8 +2,38 @@
#include <soc/soc_util.h>
#include <lib.h>
+#include <drivers/ipmi/ocp/ipmi_ocp.h>
#include "ocp_ewl.h"
+static void ipmi_send_sel_ewl_type3_err(EWL_ENTRY_HEADER *header,
+ EWL_ENTRY_MEMORY_LOCATION memory_location)
+{
+ struct ipmi_sel_mem_err sel;
+ uint8_t socketid;
+ EWL_ENTRY_TYPE3 *basic_warning;
+ basic_warning = (EWL_ENTRY_TYPE3 *)header;
+
+ /* Ignore invalid EWL DIMM location before sending SEL */
+ if (memory_location.Channel == 0xff || memory_location.Dimm == 0xff)
+ return;
+ memset(&sel, 0, sizeof(struct ipmi_sel_mem_err));
+ sel.record_id = 0x0000;
+ sel.record_type = 0xfb;
+ sel.general_info = SEL_INTEL_MEMORY_ERROR;
+ sel.timestamp = 0;
+ socketid = get_blade_id() - 1;
+ sel.socket = socketid <<= 4;
+ sel.channel = memory_location.Channel;
+ sel.dimm_slot = memory_location.Dimm;
+ sel.rsvd1 = 0xff;
+ sel.dimm_failure_type = MEM_TRAINING_ERR;
+ sel.major_code = basic_warning->Context.MajorWarningCode;
+ sel.minor_code = basic_warning->Context.MinorWarningCode;
+ sel.rsvd2 = 0xff;
+ ipmi_send_to_bmc((unsigned char *)&sel, sizeof(sel));
+ printk(BIOS_DEBUG, "ipmi send memory training error\n");
+}
+
static void process_ewl_type3(EWL_ENTRY_HEADER *header, EWL_ENTRY_MEMORY_LOCATION memory_location)
{
/* Treat warning as type 3, collect basic information and print to serial log */
@@ -47,6 +77,7 @@ void get_ewl(void)
type3 = (EWL_ENTRY_TYPE3 *)warning_header;
process_ewl_type3(warning_header, type3->MemoryLocation);
type3_flag = 1;
+ ipmi_send_sel_ewl_type3_err(warning_header, type3->MemoryLocation);
} else {
printk(BIOS_DEBUG, "EWL type: %d size:%d severity level:%d\n",
warning_header->Type,