Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  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 "cper_cxl.h"
 12#include <linux/cxl_err.h>
 13
 14#define PROT_ERR_VALID_AGENT_TYPE		BIT_ULL(0)
 15#define PROT_ERR_VALID_AGENT_ADDRESS		BIT_ULL(1)
 16#define PROT_ERR_VALID_DEVICE_ID		BIT_ULL(2)
 17#define PROT_ERR_VALID_SERIAL_NUMBER		BIT_ULL(3)
 18#define PROT_ERR_VALID_CAPABILITY		BIT_ULL(4)
 19#define PROT_ERR_VALID_DVSEC			BIT_ULL(5)
 20#define PROT_ERR_VALID_ERROR_LOG		BIT_ULL(6)
 21
 22static const char * const prot_err_agent_type_strs[] = {
 23	"Restricted CXL Device",
 24	"Restricted CXL Host Downstream Port",
 25	"CXL Device",
 26	"CXL Logical Device",
 27	"CXL Fabric Manager managed Logical Device",
 28	"CXL Root Port",
 29	"CXL Downstream Switch Port",
 30	"CXL Upstream Switch Port",
 31};
 32
 33/*
 34 * The layout of the enumeration and the values matches CXL Agent Type
 35 * field in the UEFI 2.10 Section N.2.13,
 36 */
 37enum {
 38	RCD,	/* Restricted CXL Device */
 39	RCH_DP,	/* Restricted CXL Host Downstream Port */
 40	DEVICE,	/* CXL Device */
 41	LD,	/* CXL Logical Device */
 42	FMLD,	/* CXL Fabric Manager managed Logical Device */
 43	RP,	/* CXL Root Port */
 44	DSP,	/* CXL Downstream Switch Port */
 45	USP,	/* CXL Upstream Switch Port */
 46};
 47
 48void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err)
 49{
 50	if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE)
 51		pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type,
 52			prot_err->agent_type < ARRAY_SIZE(prot_err_agent_type_strs)
 53			? prot_err_agent_type_strs[prot_err->agent_type]
 54			: "unknown");
 55
 56	if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS) {
 57		switch (prot_err->agent_type) {
 58		/*
 59		 * According to UEFI 2.10 Section N.2.13, the term CXL Device
 60		 * is used to refer to Restricted CXL Device, CXL Device, CXL
 61		 * Logical Device or a CXL Fabric Manager Managed Logical
 62		 * Device.
 63		 */
 64		case RCD:
 65		case DEVICE:
 66		case LD:
 67		case FMLD:
 68		case RP:
 69		case DSP:
 70		case USP:
 71			pr_info("%s agent_address: %04x:%02x:%02x.%x\n",
 72				pfx, prot_err->agent_addr.segment,
 73				prot_err->agent_addr.bus,
 74				prot_err->agent_addr.device,
 75				prot_err->agent_addr.function);
 76			break;
 77		case RCH_DP:
 78			pr_info("%s rcrb_base_address: 0x%016llx\n", pfx,
 79				prot_err->agent_addr.rcrb_base_addr);
 80			break;
 81		default:
 82			break;
 83		}
 84	}
 85
 86	if (prot_err->valid_bits & PROT_ERR_VALID_DEVICE_ID) {
 87		const __u8 *class_code;
 88
 89		switch (prot_err->agent_type) {
 90		case RCD:
 91		case DEVICE:
 92		case LD:
 93		case FMLD:
 94		case RP:
 95		case DSP:
 96		case USP:
 97			pr_info("%s slot: %d\n", pfx,
 98				prot_err->device_id.slot >> CPER_PCIE_SLOT_SHIFT);
 99			pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n",
100				pfx, prot_err->device_id.vendor_id,
101				prot_err->device_id.device_id);
102			pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n",
103				pfx, prot_err->device_id.subsystem_vendor_id,
104				prot_err->device_id.subsystem_id);
105			class_code = prot_err->device_id.class_code;
106			pr_info("%s class_code: %02x%02x\n", pfx,
107				class_code[1], class_code[0]);
108			break;
109		default:
110			break;
111		}
112	}
113
114	if (prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER) {
115		switch (prot_err->agent_type) {
116		case RCD:
117		case DEVICE:
118		case LD:
119		case FMLD:
120			pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx,
121				prot_err->dev_serial_num.lower_dw,
122				prot_err->dev_serial_num.upper_dw);
123			break;
124		default:
125			break;
126		}
127	}
128
129	if (prot_err->valid_bits & PROT_ERR_VALID_CAPABILITY) {
130		switch (prot_err->agent_type) {
131		case RCD:
132		case DEVICE:
133		case LD:
134		case FMLD:
135		case RP:
136		case DSP:
137		case USP:
138			print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4,
139				       prot_err->capability,
140				       sizeof(prot_err->capability), 0);
141			break;
142		default:
143			break;
144		}
145	}
146
147	if (prot_err->valid_bits & PROT_ERR_VALID_DVSEC) {
148		pr_info("%s DVSEC length: 0x%04x\n", pfx, prot_err->dvsec_len);
149
150		pr_info("%s CXL DVSEC:\n", pfx);
151		print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, (prot_err + 1),
152			       prot_err->dvsec_len, 0);
153	}
154
155	if (prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG) {
156		size_t size = sizeof(*prot_err) + prot_err->dvsec_len;
157		struct cxl_ras_capability_regs *cxl_ras;
158
159		pr_info("%s Error log length: 0x%04x\n", pfx, prot_err->err_len);
160
161		pr_info("%s CXL Error Log:\n", pfx);
162		cxl_ras = (struct cxl_ras_capability_regs *)((long)prot_err + size);
163		pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx,
164			cxl_ras->uncor_status);
165		pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx,
166			cxl_ras->uncor_mask);
167		pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx,
168			cxl_ras->uncor_severity);
169		pr_info("%s cxl_ras_cor_status: 0x%08x", pfx,
170			cxl_ras->cor_status);
171		pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx,
172			cxl_ras->cor_mask);
173		pr_info("%s cap_control: 0x%08x\n", pfx,
174			cxl_ras->cap_control);
175		pr_info("%s Header Log Registers:\n", pfx);
176		print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, cxl_ras->header_log,
177			       sizeof(cxl_ras->header_log), 0);
178	}
179}