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