Add support for decoding CXL Component Events DRAM Event Record as defined in CXL rev 3.0 section 8.2.9.2.1.2. Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@xxxxxxx> --- drivers/firmware/efi/cper.c | 8 ++++ drivers/firmware/efi/cper_cxl.c | 79 +++++++++++++++++++++++++++++++++ drivers/firmware/efi/cper_cxl.h | 28 ++++++++++++ 3 files changed, 115 insertions(+) diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index b911b1f574db..1d182487fa13 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -615,6 +615,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata cper_print_gen_media(newpfx, gmer); else goto err_section_too_small; + } else if (guid_equal(sec_type, &CPER_SEC_CXL_DRAM)) { + struct cper_sec_comp_event *dram = acpi_hest_get_payload(gdata); + + printk("%ssection_type: CXL DRAM Event\n", newpfx); + if (gdata->error_data_length >= sizeof(*dram)) + cper_print_dram(newpfx, dram); + else + goto err_section_too_small; } else { const void *err = acpi_hest_get_payload(gdata); diff --git a/drivers/firmware/efi/cper_cxl.c b/drivers/firmware/efi/cper_cxl.c index 8f7b88cc574b..3fba360b7dc6 100644 --- a/drivers/firmware/efi/cper_cxl.c +++ b/drivers/firmware/efi/cper_cxl.c @@ -30,6 +30,15 @@ #define GMER_VALID_DEVICE BIT_ULL(2) #define GMER_VALID_COMP_ID BIT_ULL(3) +#define DRAM_VALID_CHANNEL BIT_ULL(0) +#define DRAM_VALID_RANK BIT_ULL(1) +#define DRAM_VALID_NIBBLE_MASK BIT_ULL(2) +#define DRAM_VALID_BANK_GROUP BIT_ULL(3) +#define DRAM_VALID_BANK BIT_ULL(4) +#define DRAM_VALID_ROW BIT_ULL(5) +#define DRAM_VALID_COLUMN BIT_ULL(6) +#define DRAM_VALID_CORRECTION_MASK BIT_ULL(7) + /* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */ struct cxl_ras_capability_regs { u32 uncor_status; @@ -103,6 +112,13 @@ static const char * const transaction_type_strs[] = { "internal media management", }; +static const char * const dram_mem_type_strs[] = { + "media ECC error", + "scrub media ECC error", + "invalid address", + "data path error", +}; + void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err) { if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE) @@ -330,3 +346,66 @@ void cper_print_gen_media(const char *pfx, const struct cper_sec_comp_event *eve sizeof(gmer->comp_id), 0); } } + +void cper_print_dram(const char *pfx, const struct cper_sec_comp_event *event) +{ + struct cper_sec_dram *dram; + + cper_print_comp_event(pfx, event); + + if (!(event->valid_bits & COMP_EVENT_VALID_EVENT_LOG)) + return; + + dram = (struct cper_sec_dram *)(event + 1); + + cper_print_event_record(pfx, &dram->record); + + pr_info("%s device physical address: 0x%016llx\n", pfx, dram->dpa); + pr_info("%s memory event descriptor: 0x%02x\n", pfx, dram->descriptor); + cper_print_bits(pfx, dram->descriptor, mem_evt_descriptor_strs, + ARRAY_SIZE(mem_evt_descriptor_strs)); + + pr_info("%s memory event type: %d, %s\n", pfx, dram->type, + dram->type < ARRAY_SIZE(dram_mem_type_strs) + ? dram_mem_type_strs[dram->type] : "unknown"); + + pr_info("%s transaction type: %d, %s\n", pfx, dram->transaction_type, + dram->transaction_type < ARRAY_SIZE(transaction_type_strs) + ? transaction_type_strs[dram->transaction_type] : "unknown"); + + if (dram->validity_flags & DRAM_VALID_CHANNEL) + pr_info("%s channel: 0x%02x\n", pfx, dram->channel); + + if (dram->validity_flags & DRAM_VALID_RANK) + pr_info("%s rank: 0x%02x\n", pfx, dram->rank); + + if (dram->validity_flags & DRAM_VALID_NIBBLE_MASK) { + const __u8 *nibble; + + nibble = dram->nibble_mask; + pr_info("%s nibble mask: %02x%02x%02x\n", pfx, nibble[2], + nibble[1], nibble[0]); + } + + if (dram->validity_flags & DRAM_VALID_BANK_GROUP) + pr_info("%s bank group: 0x%02x\n", pfx, dram->bank_group); + + if (dram->validity_flags & DRAM_VALID_BANK) + pr_info("%s bank: 0x%02x\n", pfx, dram->bank); + + if (dram->validity_flags & DRAM_VALID_ROW) { + const __u8 *row; + + row = dram->row; + pr_info("%s row: %02x%02x%02x\n", pfx, row[2], row[1], row[0]); + } + + if (dram->validity_flags & DRAM_VALID_COLUMN) + pr_info("%s column: 0x%04x\n", pfx, dram->column); + + if (dram->validity_flags & DRAM_VALID_CORRECTION_MASK) { + pr_info("%s correction mask :\n", pfx); + print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, + dram->cor_mask, sizeof(dram->cor_mask), 0); + } +} diff --git a/drivers/firmware/efi/cper_cxl.h b/drivers/firmware/efi/cper_cxl.h index 94528db208de..967847b571cb 100644 --- a/drivers/firmware/efi/cper_cxl.h +++ b/drivers/firmware/efi/cper_cxl.h @@ -20,6 +20,11 @@ GUID_INIT(0xFBCD0A77, 0xC260, 0x417F, 0x85, 0xA9, 0x08, 0x8B, \ 0x16, 0x21, 0xEB, 0xA6) +/* CXL DRAM Section */ +#define CPER_SEC_CXL_DRAM \ + GUID_INIT(0x601DCBB3, 0x9C06, 0x4EAB, 0xB8, 0xAF, 0x4E, 0x9B, \ + 0xFB, 0x5C, 0x96, 0x24) + #pragma pack(1) /* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */ @@ -120,9 +125,32 @@ struct cper_sec_gen_media { u8 reserved[46]; }; +/* + * CXL DRAM Event Record + * CXL rev 3.0 sec 8.2.9.2.1.2; Table 8-44 + */ +struct cper_sec_dram { + struct common_event_record record; + u64 dpa; + u8 descriptor; + u8 type; + u8 transaction_type; + u16 validity_flags; + u8 channel; + u8 rank; + u8 nibble_mask[3]; + u8 bank_group; + u8 bank; + u8 row[3]; + u16 column; + u8 cor_mask[32]; + u8 reserved[23]; +}; + #pragma pack() void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err); void cper_print_gen_media(const char *pfx, const struct cper_sec_comp_event *event); +void cper_print_dram(const char *pfx, const struct cper_sec_comp_event *event); #endif //__CPER_CXL_ -- 2.17.1