1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * UEFI Common Platform Error Record (CPER) support for CXL Section. 4 * 5 * Copyright (C) 2022 Advanced Micro Devices, Inc. 6 * 7 * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> 8 */ 9 10 #include <linux/cper.h> 11 #include <cxl/event.h> 12 13 static const char * const prot_err_agent_type_strs[] = { 14 "Restricted CXL Device", 15 "Restricted CXL Host Downstream Port", 16 "CXL Device", 17 "CXL Logical Device", 18 "CXL Fabric Manager managed Logical Device", 19 "CXL Root Port", 20 "CXL Downstream Switch Port", 21 "CXL Upstream Switch Port", 22 }; 23 24 void cxl_cper_print_prot_err(const char *pfx, 25 const struct cxl_cper_sec_prot_err *prot_err) 26 { 27 if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE) 28 pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type, 29 prot_err->agent_type < ARRAY_SIZE(prot_err_agent_type_strs) 30 ? prot_err_agent_type_strs[prot_err->agent_type] 31 : "unknown"); 32 33 if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS) { 34 switch (prot_err->agent_type) { 35 /* 36 * According to UEFI 2.10 Section N.2.13, the term CXL Device 37 * is used to refer to Restricted CXL Device, CXL Device, CXL 38 * Logical Device or a CXL Fabric Manager Managed Logical 39 * Device. 40 */ 41 case RCD: 42 case DEVICE: 43 case LD: 44 case FMLD: 45 case RP: 46 case DSP: 47 case USP: 48 pr_info("%s agent_address: %04x:%02x:%02x.%x\n", 49 pfx, prot_err->agent_addr.segment, 50 prot_err->agent_addr.bus, 51 prot_err->agent_addr.device, 52 prot_err->agent_addr.function); 53 break; 54 case RCH_DP: 55 pr_info("%s rcrb_base_address: 0x%016llx\n", pfx, 56 prot_err->agent_addr.rcrb_base_addr); 57 break; 58 default: 59 break; 60 } 61 } 62 63 if (prot_err->valid_bits & PROT_ERR_VALID_DEVICE_ID) { 64 const __u8 *class_code; 65 66 switch (prot_err->agent_type) { 67 case RCD: 68 case DEVICE: 69 case LD: 70 case FMLD: 71 case RP: 72 case DSP: 73 case USP: 74 pr_info("%s slot: %d\n", pfx, 75 prot_err->device_id.slot >> CPER_PCIE_SLOT_SHIFT); 76 pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n", 77 pfx, prot_err->device_id.vendor_id, 78 prot_err->device_id.device_id); 79 pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n", 80 pfx, prot_err->device_id.subsystem_vendor_id, 81 prot_err->device_id.subsystem_id); 82 class_code = prot_err->device_id.class_code; 83 pr_info("%s class_code: %02x%02x\n", pfx, 84 class_code[1], class_code[0]); 85 break; 86 default: 87 break; 88 } 89 } 90 91 if (prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER) { 92 switch (prot_err->agent_type) { 93 case RCD: 94 case DEVICE: 95 case LD: 96 case FMLD: 97 pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx, 98 prot_err->dev_serial_num.lower_dw, 99 prot_err->dev_serial_num.upper_dw); 100 break; 101 default: 102 break; 103 } 104 } 105 106 if (prot_err->valid_bits & PROT_ERR_VALID_CAPABILITY) { 107 switch (prot_err->agent_type) { 108 case RCD: 109 case DEVICE: 110 case LD: 111 case FMLD: 112 case RP: 113 case DSP: 114 case USP: 115 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, 116 prot_err->capability, 117 sizeof(prot_err->capability), 0); 118 break; 119 default: 120 break; 121 } 122 } 123 124 if (prot_err->valid_bits & PROT_ERR_VALID_DVSEC) { 125 pr_info("%s DVSEC length: 0x%04x\n", pfx, prot_err->dvsec_len); 126 127 pr_info("%s CXL DVSEC:\n", pfx); 128 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, (prot_err + 1), 129 prot_err->dvsec_len, 0); 130 } 131 132 if (prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG) { 133 size_t size = sizeof(*prot_err) + prot_err->dvsec_len; 134 struct cxl_ras_capability_regs *cxl_ras; 135 136 pr_info("%s Error log length: 0x%04x\n", pfx, prot_err->err_len); 137 138 pr_info("%s CXL Error Log:\n", pfx); 139 cxl_ras = (struct cxl_ras_capability_regs *)((long)prot_err + size); 140 pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx, 141 cxl_ras->uncor_status); 142 pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx, 143 cxl_ras->uncor_mask); 144 pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx, 145 cxl_ras->uncor_severity); 146 pr_info("%s cxl_ras_cor_status: 0x%08x", pfx, 147 cxl_ras->cor_status); 148 pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx, 149 cxl_ras->cor_mask); 150 pr_info("%s cap_control: 0x%08x\n", pfx, 151 cxl_ras->cap_control); 152 pr_info("%s Header Log Registers:\n", pfx); 153 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, cxl_ras->header_log, 154 sizeof(cxl_ras->header_log), 0); 155 } 156 } 157