diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
commit | ace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch) | |
tree | b2d64bc10158fdd5497876388cd68142ca374ed3 /drivers/firmware/efi/cper_cxl.c | |
parent | Initial commit. (diff) | |
download | linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip |
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/firmware/efi/cper_cxl.c')
-rw-r--r-- | drivers/firmware/efi/cper_cxl.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/drivers/firmware/efi/cper_cxl.c b/drivers/firmware/efi/cper_cxl.c new file mode 100644 index 0000000000..a55771b99a --- /dev/null +++ b/drivers/firmware/efi/cper_cxl.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * UEFI Common Platform Error Record (CPER) support for CXL Section. + * + * Copyright (C) 2022 Advanced Micro Devices, Inc. + * + * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> + */ + +#include <linux/cper.h> +#include "cper_cxl.h" + +#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0) +#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1) +#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2) +#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3) +#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4) +#define PROT_ERR_VALID_DVSEC BIT_ULL(5) +#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6) + +/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */ +struct cxl_ras_capability_regs { + u32 uncor_status; + u32 uncor_mask; + u32 uncor_severity; + u32 cor_status; + u32 cor_mask; + u32 cap_control; + u32 header_log[16]; +}; + +static const char * const prot_err_agent_type_strs[] = { + "Restricted CXL Device", + "Restricted CXL Host Downstream Port", + "CXL Device", + "CXL Logical Device", + "CXL Fabric Manager managed Logical Device", + "CXL Root Port", + "CXL Downstream Switch Port", + "CXL Upstream Switch Port", +}; + +/* + * The layout of the enumeration and the values matches CXL Agent Type + * field in the UEFI 2.10 Section N.2.13, + */ +enum { + RCD, /* Restricted CXL Device */ + RCH_DP, /* Restricted CXL Host Downstream Port */ + DEVICE, /* CXL Device */ + LD, /* CXL Logical Device */ + FMLD, /* CXL Fabric Manager managed Logical Device */ + RP, /* CXL Root Port */ + DSP, /* CXL Downstream Switch Port */ + USP, /* CXL Upstream Switch Port */ +}; + +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) + pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type, + prot_err->agent_type < ARRAY_SIZE(prot_err_agent_type_strs) + ? prot_err_agent_type_strs[prot_err->agent_type] + : "unknown"); + + if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS) { + switch (prot_err->agent_type) { + /* + * According to UEFI 2.10 Section N.2.13, the term CXL Device + * is used to refer to Restricted CXL Device, CXL Device, CXL + * Logical Device or a CXL Fabric Manager Managed Logical + * Device. + */ + case RCD: + case DEVICE: + case LD: + case FMLD: + case RP: + case DSP: + case USP: + pr_info("%s agent_address: %04x:%02x:%02x.%x\n", + pfx, prot_err->agent_addr.segment, + prot_err->agent_addr.bus, + prot_err->agent_addr.device, + prot_err->agent_addr.function); + break; + case RCH_DP: + pr_info("%s rcrb_base_address: 0x%016llx\n", pfx, + prot_err->agent_addr.rcrb_base_addr); + break; + default: + break; + } + } + + if (prot_err->valid_bits & PROT_ERR_VALID_DEVICE_ID) { + const __u8 *class_code; + + switch (prot_err->agent_type) { + case RCD: + case DEVICE: + case LD: + case FMLD: + case RP: + case DSP: + case USP: + pr_info("%s slot: %d\n", pfx, + prot_err->device_id.slot >> CPER_PCIE_SLOT_SHIFT); + pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n", + pfx, prot_err->device_id.vendor_id, + prot_err->device_id.device_id); + pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n", + pfx, prot_err->device_id.subsystem_vendor_id, + prot_err->device_id.subsystem_id); + class_code = prot_err->device_id.class_code; + pr_info("%s class_code: %02x%02x\n", pfx, + class_code[1], class_code[0]); + break; + default: + break; + } + } + + if (prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER) { + switch (prot_err->agent_type) { + case RCD: + case DEVICE: + case LD: + case FMLD: + pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx, + prot_err->dev_serial_num.lower_dw, + prot_err->dev_serial_num.upper_dw); + break; + default: + break; + } + } + + if (prot_err->valid_bits & PROT_ERR_VALID_CAPABILITY) { + switch (prot_err->agent_type) { + case RCD: + case DEVICE: + case LD: + case FMLD: + case RP: + case DSP: + case USP: + print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, + prot_err->capability, + sizeof(prot_err->capability), 0); + break; + default: + break; + } + } + + if (prot_err->valid_bits & PROT_ERR_VALID_DVSEC) { + pr_info("%s DVSEC length: 0x%04x\n", pfx, prot_err->dvsec_len); + + pr_info("%s CXL DVSEC:\n", pfx); + print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, (prot_err + 1), + prot_err->dvsec_len, 0); + } + + if (prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG) { + size_t size = sizeof(*prot_err) + prot_err->dvsec_len; + struct cxl_ras_capability_regs *cxl_ras; + + pr_info("%s Error log length: 0x%04x\n", pfx, prot_err->err_len); + + pr_info("%s CXL Error Log:\n", pfx); + cxl_ras = (struct cxl_ras_capability_regs *)((long)prot_err + size); + pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx, + cxl_ras->uncor_status); + pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx, + cxl_ras->uncor_mask); + pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx, + cxl_ras->uncor_severity); + pr_info("%s cxl_ras_cor_status: 0x%08x", pfx, + cxl_ras->cor_status); + pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx, + cxl_ras->cor_mask); + pr_info("%s cap_control: 0x%08x\n", pfx, + cxl_ras->cap_control); + pr_info("%s Header Log Registers:\n", pfx); + print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, cxl_ras->header_log, + sizeof(cxl_ras->header_log), 0); + } +} |