drivers/ocp/ewl: Add sending Meta's BMC SEL for memory training error

Add sending Meta's BMC SEL for memory training error occurred in EWL
type 3 error.

The detail definition of EWL (Enhanced Warning Log) can be found in the
specification document -- BIOS Data ACPI Table (BDAT) Interface
Specification v4.0 Draft 5:
https://uefi.org/sites/default/files/resources/BDAT%20Specification%20v4.0%20Draft5_0.pdf

Change-Id: I664e9d3da7910b47260881c0df64159c8dbe2dca
Signed-off-by: Shelly Chang <Shelly_Chang@wiwynn.com>
Signed-off-by: Johnny Lin <johnny_lin@wiwynn.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/69147
Reviewed-by: Jonathan Zhang <jon.zhixiong.zhang@gmail.com>
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Shelly Chang 2022-04-11 10:50:40 +08:00 committed by Felix Held
parent 930dbc0d04
commit e17fc5dc0b
3 changed files with 58 additions and 1 deletions

View File

@ -1,5 +1,5 @@
ramstage-$(CONFIG_IPMI_OCP) += ipmi_ocp.c ipmi_sel.c ramstage-$(CONFIG_IPMI_OCP) += ipmi_ocp.c ipmi_sel.c
ifeq ($(CONFIG_IPMI_OCP),y) 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 smm-$(CONFIG_IPMI_BMC_SEL) += ipmi_sel.c
endif endif

View File

@ -89,6 +89,16 @@ enum fail_type {
PCIE_ECRC_EVNT = 5, 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 { struct ipmi_sel_pcie_dev_fail {
uint16_t record_id; uint16_t record_id;
uint8_t record_type; uint8_t record_type;
@ -102,6 +112,21 @@ struct ipmi_sel_pcie_dev_fail {
uint8_t rsvd2; uint8_t rsvd2;
} __packed; } __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 { struct ipmi_config_rsp {
uint8_t board_sku_id; uint8_t board_sku_id;
uint8_t board_rev_id; uint8_t board_rev_id;
@ -111,6 +136,7 @@ struct ipmi_config_rsp {
#define SEL_RECORD_ID 0x01 #define SEL_RECORD_ID 0x01
#define SEL_PCIE_DEV_ERR 0x20 #define SEL_PCIE_DEV_ERR 0x20
#define SEL_INTEL_MEMORY_ERROR 0x21
#define SEL_PCIE_IIO_ERR 0x23 #define SEL_PCIE_IIO_ERR 0x23
#define SEL_PCIE_DEV_FAIL_ID 0x29 #define SEL_PCIE_DEV_FAIL_ID 0x29

View File

@ -2,8 +2,38 @@
#include <soc/soc_util.h> #include <soc/soc_util.h>
#include <lib.h> #include <lib.h>
#include <drivers/ipmi/ocp/ipmi_ocp.h>
#include "ocp_ewl.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) 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 */ /* 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; type3 = (EWL_ENTRY_TYPE3 *)warning_header;
process_ewl_type3(warning_header, type3->MemoryLocation); process_ewl_type3(warning_header, type3->MemoryLocation);
type3_flag = 1; type3_flag = 1;
ipmi_send_sel_ewl_type3_err(warning_header, type3->MemoryLocation);
} else { } else {
printk(BIOS_DEBUG, "EWL type: %d size:%d severity level:%d\n", printk(BIOS_DEBUG, "EWL type: %d size:%d severity level:%d\n",
warning_header->Type, warning_header->Type,