1 // SPDX-License-Identifier: GPL-2.0-only
3 * UEFI Common Platform Error Record (CPER) support for CXL Section.
5 * Copyright (C) 2022 Advanced Micro Devices, Inc.
7 * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
10 #include <linux/cper.h>
13 #define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
14 #define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
15 #define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
16 #define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
17 #define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
18 #define PROT_ERR_VALID_DVSEC BIT_ULL(5)
19 #define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
21 /* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
22 struct cxl_ras_capability_regs
{
32 static const char * const prot_err_agent_type_strs
[] = {
33 "Restricted CXL Device",
34 "Restricted CXL Host Downstream Port",
37 "CXL Fabric Manager managed Logical Device",
39 "CXL Downstream Switch Port",
40 "CXL Upstream Switch Port",
44 * The layout of the enumeration and the values matches CXL Agent Type
45 * field in the UEFI 2.10 Section N.2.13,
48 RCD
, /* Restricted CXL Device */
49 RCH_DP
, /* Restricted CXL Host Downstream Port */
50 DEVICE
, /* CXL Device */
51 LD
, /* CXL Logical Device */
52 FMLD
, /* CXL Fabric Manager managed Logical Device */
53 RP
, /* CXL Root Port */
54 DSP
, /* CXL Downstream Switch Port */
55 USP
, /* CXL Upstream Switch Port */
58 void cper_print_prot_err(const char *pfx
, const struct cper_sec_prot_err
*prot_err
)
60 if (prot_err
->valid_bits
& PROT_ERR_VALID_AGENT_TYPE
)
61 pr_info("%s agent_type: %d, %s\n", pfx
, prot_err
->agent_type
,
62 prot_err
->agent_type
< ARRAY_SIZE(prot_err_agent_type_strs
)
63 ? prot_err_agent_type_strs
[prot_err
->agent_type
]
66 if (prot_err
->valid_bits
& PROT_ERR_VALID_AGENT_ADDRESS
) {
67 switch (prot_err
->agent_type
) {
69 * According to UEFI 2.10 Section N.2.13, the term CXL Device
70 * is used to refer to Restricted CXL Device, CXL Device, CXL
71 * Logical Device or a CXL Fabric Manager Managed Logical
81 pr_info("%s agent_address: %04x:%02x:%02x.%x\n",
82 pfx
, prot_err
->agent_addr
.segment
,
83 prot_err
->agent_addr
.bus
,
84 prot_err
->agent_addr
.device
,
85 prot_err
->agent_addr
.function
);
88 pr_info("%s rcrb_base_address: 0x%016llx\n", pfx
,
89 prot_err
->agent_addr
.rcrb_base_addr
);
96 if (prot_err
->valid_bits
& PROT_ERR_VALID_DEVICE_ID
) {
97 const __u8
*class_code
;
99 switch (prot_err
->agent_type
) {
107 pr_info("%s slot: %d\n", pfx
,
108 prot_err
->device_id
.slot
>> CPER_PCIE_SLOT_SHIFT
);
109 pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n",
110 pfx
, prot_err
->device_id
.vendor_id
,
111 prot_err
->device_id
.device_id
);
112 pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n",
113 pfx
, prot_err
->device_id
.subsystem_vendor_id
,
114 prot_err
->device_id
.subsystem_id
);
115 class_code
= prot_err
->device_id
.class_code
;
116 pr_info("%s class_code: %02x%02x\n", pfx
,
117 class_code
[1], class_code
[0]);
124 if (prot_err
->valid_bits
& PROT_ERR_VALID_SERIAL_NUMBER
) {
125 switch (prot_err
->agent_type
) {
130 pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx
,
131 prot_err
->dev_serial_num
.lower_dw
,
132 prot_err
->dev_serial_num
.upper_dw
);
139 if (prot_err
->valid_bits
& PROT_ERR_VALID_CAPABILITY
) {
140 switch (prot_err
->agent_type
) {
148 print_hex_dump(pfx
, "", DUMP_PREFIX_OFFSET
, 16, 4,
149 prot_err
->capability
,
150 sizeof(prot_err
->capability
), 0);
157 if (prot_err
->valid_bits
& PROT_ERR_VALID_DVSEC
) {
158 pr_info("%s DVSEC length: 0x%04x\n", pfx
, prot_err
->dvsec_len
);
160 pr_info("%s CXL DVSEC:\n", pfx
);
161 print_hex_dump(pfx
, "", DUMP_PREFIX_OFFSET
, 16, 4, (prot_err
+ 1),
162 prot_err
->dvsec_len
, 0);
165 if (prot_err
->valid_bits
& PROT_ERR_VALID_ERROR_LOG
) {
166 size_t size
= sizeof(*prot_err
) + prot_err
->dvsec_len
;
167 struct cxl_ras_capability_regs
*cxl_ras
;
169 pr_info("%s Error log length: 0x%04x\n", pfx
, prot_err
->err_len
);
171 pr_info("%s CXL Error Log:\n", pfx
);
172 cxl_ras
= (struct cxl_ras_capability_regs
*)((long)prot_err
+ size
);
173 pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx
,
174 cxl_ras
->uncor_status
);
175 pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx
,
176 cxl_ras
->uncor_mask
);
177 pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx
,
178 cxl_ras
->uncor_severity
);
179 pr_info("%s cxl_ras_cor_status: 0x%08x", pfx
,
180 cxl_ras
->cor_status
);
181 pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx
,
183 pr_info("%s cap_control: 0x%08x\n", pfx
,
184 cxl_ras
->cap_control
);
185 pr_info("%s Header Log Registers:\n", pfx
);
186 print_hex_dump(pfx
, "", DUMP_PREFIX_OFFSET
, 16, 4, cxl_ras
->header_log
,
187 sizeof(cxl_ras
->header_log
), 0);