xref: /linux/include/cxl/event.h (revision 01ecadbe09b6c685de413ada8ba6688e9467c4b3)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright(c) 2023 Intel Corporation. */
3 #ifndef _LINUX_CXL_EVENT_H
4 #define _LINUX_CXL_EVENT_H
5 
6 #include <linux/types.h>
7 #include <linux/uuid.h>
8 #include <linux/workqueue_types.h>
9 
10 /*
11  * Common Event Record Format
12  * CXL rev 3.0 section 8.2.9.2.1; Table 8-42
13  */
14 struct cxl_event_record_hdr {
15 	u8 length;
16 	u8 flags[3];
17 	__le16 handle;
18 	__le16 related_handle;
19 	__le64 timestamp;
20 	u8 maint_op_class;
21 	u8 maint_op_sub_class;
22 	u8 reserved[14];
23 } __packed;
24 
25 struct cxl_event_media_hdr {
26 	struct cxl_event_record_hdr hdr;
27 	__le64 phys_addr;
28 	u8 descriptor;
29 	u8 type;
30 	u8 transaction_type;
31 	/*
32 	 * The meaning of Validity Flags from bit 2 is
33 	 * different across DRAM and General Media records
34 	 */
35 	u8 validity_flags[2];
36 	u8 channel;
37 	u8 rank;
38 } __packed;
39 
40 #define CXL_EVENT_RECORD_DATA_LENGTH 0x50
41 struct cxl_event_generic {
42 	struct cxl_event_record_hdr hdr;
43 	u8 data[CXL_EVENT_RECORD_DATA_LENGTH];
44 } __packed;
45 
46 /*
47  * General Media Event Record
48  * CXL rev 3.1 Section 8.2.9.2.1.1; Table 8-45
49  */
50 #define CXL_EVENT_GEN_MED_COMP_ID_SIZE	0x10
51 struct cxl_event_gen_media {
52 	struct cxl_event_media_hdr media_hdr;
53 	u8 device[3];
54 	u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
55 	u8 cme_threshold_ev_flags;
56 	u8 cme_count[3];
57 	u8 sub_type;
58 	u8 reserved[41];
59 } __packed;
60 
61 /*
62  * DRAM Event Record - DER
63  * CXL rev 3.1 section 8.2.9.2.1.2; Table 8-46
64  */
65 #define CXL_EVENT_DER_CORRECTION_MASK_SIZE	0x20
66 struct cxl_event_dram {
67 	struct cxl_event_media_hdr media_hdr;
68 	u8 nibble_mask[3];
69 	u8 bank_group;
70 	u8 bank;
71 	u8 row[3];
72 	u8 column[2];
73 	u8 correction_mask[CXL_EVENT_DER_CORRECTION_MASK_SIZE];
74 	u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
75 	u8 sub_channel;
76 	u8 cme_threshold_ev_flags;
77 	u8 cvme_count[3];
78 	u8 sub_type;
79 	u8 reserved;
80 } __packed;
81 
82 /*
83  * Get Health Info Record
84  * CXL rev 3.1 section 8.2.9.9.3.1; Table 8-133
85  */
86 struct cxl_get_health_info {
87 	u8 health_status;
88 	u8 media_status;
89 	u8 add_status;
90 	u8 life_used;
91 	u8 device_temp[2];
92 	u8 dirty_shutdown_cnt[4];
93 	u8 cor_vol_err_cnt[4];
94 	u8 cor_per_err_cnt[4];
95 } __packed;
96 
97 /*
98  * Memory Module Event Record
99  * CXL rev 3.1 section 8.2.9.2.1.3; Table 8-47
100  */
101 struct cxl_event_mem_module {
102 	struct cxl_event_record_hdr hdr;
103 	u8 event_type;
104 	struct cxl_get_health_info info;
105 	u8 validity_flags[2];
106 	u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
107 	u8 event_sub_type;
108 	u8 reserved[0x2a];
109 } __packed;
110 
111 union cxl_event {
112 	struct cxl_event_generic generic;
113 	struct cxl_event_gen_media gen_media;
114 	struct cxl_event_dram dram;
115 	struct cxl_event_mem_module mem_module;
116 	/* dram & gen_media event header */
117 	struct cxl_event_media_hdr media_hdr;
118 } __packed;
119 
120 /*
121  * Common Event Record Format; in event logs
122  * CXL rev 3.0 section 8.2.9.2.1; Table 8-42
123  */
124 struct cxl_event_record_raw {
125 	uuid_t id;
126 	union cxl_event event;
127 } __packed;
128 
129 enum cxl_event_type {
130 	CXL_CPER_EVENT_GENERIC,
131 	CXL_CPER_EVENT_GEN_MEDIA,
132 	CXL_CPER_EVENT_DRAM,
133 	CXL_CPER_EVENT_MEM_MODULE,
134 };
135 
136 #define CPER_CXL_DEVICE_ID_VALID		BIT(0)
137 #define CPER_CXL_DEVICE_SN_VALID		BIT(1)
138 #define CPER_CXL_COMP_EVENT_LOG_VALID		BIT(2)
139 struct cxl_cper_event_rec {
140 	struct {
141 		u32 length;
142 		u64 validation_bits;
143 		struct cper_cxl_event_devid {
144 			u16 vendor_id;
145 			u16 device_id;
146 			u8 func_num;
147 			u8 device_num;
148 			u8 bus_num;
149 			u16 segment_num;
150 			u16 slot_num; /* bits 2:0 reserved */
151 			u8 reserved;
152 		} __packed device_id;
153 		struct cper_cxl_event_sn {
154 			u32 lower_dw;
155 			u32 upper_dw;
156 		} __packed dev_serial_num;
157 	} __packed hdr;
158 
159 	union cxl_event event;
160 } __packed;
161 
162 struct cxl_cper_work_data {
163 	enum cxl_event_type event_type;
164 	struct cxl_cper_event_rec rec;
165 };
166 
167 #define PROT_ERR_VALID_AGENT_TYPE		BIT_ULL(0)
168 #define PROT_ERR_VALID_AGENT_ADDRESS		BIT_ULL(1)
169 #define PROT_ERR_VALID_DEVICE_ID		BIT_ULL(2)
170 #define PROT_ERR_VALID_SERIAL_NUMBER		BIT_ULL(3)
171 #define PROT_ERR_VALID_CAPABILITY		BIT_ULL(4)
172 #define PROT_ERR_VALID_DVSEC			BIT_ULL(5)
173 #define PROT_ERR_VALID_ERROR_LOG		BIT_ULL(6)
174 
175 /*
176  * The layout of the enumeration and the values matches CXL Agent Type
177  * field in the UEFI 2.10 Section N.2.13,
178  */
179 enum {
180 	RCD,	/* Restricted CXL Device */
181 	RCH_DP,	/* Restricted CXL Host Downstream Port */
182 	DEVICE,	/* CXL Device */
183 	LD,	/* CXL Logical Device */
184 	FMLD,	/* CXL Fabric Manager managed Logical Device */
185 	RP,	/* CXL Root Port */
186 	DSP,	/* CXL Downstream Switch Port */
187 	USP,	/* CXL Upstream Switch Port */
188 };
189 
190 #pragma pack(1)
191 
192 /* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
193 struct cxl_cper_sec_prot_err {
194 	u64 valid_bits;
195 	u8 agent_type;
196 	u8 reserved[7];
197 
198 	/*
199 	 * Except for RCH Downstream Port, all the remaining CXL Agent
200 	 * types are uniquely identified by the PCIe compatible SBDF number.
201 	 */
202 	union {
203 		u64 rcrb_base_addr;
204 		struct {
205 			u8 function;
206 			u8 device;
207 			u8 bus;
208 			u16 segment;
209 			u8 reserved_1[3];
210 		};
211 	} agent_addr;
212 
213 	struct {
214 		u16 vendor_id;
215 		u16 device_id;
216 		u16 subsystem_vendor_id;
217 		u16 subsystem_id;
218 		u8 class_code[2];
219 		u16 slot;
220 		u8 reserved_1[4];
221 	} device_id;
222 
223 	struct {
224 		u32 lower_dw;
225 		u32 upper_dw;
226 	} dev_serial_num;
227 
228 	u8 capability[60];
229 	u16 dvsec_len;
230 	u16 err_len;
231 	u8 reserved_2[4];
232 };
233 
234 #pragma pack()
235 
236 /* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
237 struct cxl_ras_capability_regs {
238 	u32 uncor_status;
239 	u32 uncor_mask;
240 	u32 uncor_severity;
241 	u32 cor_status;
242 	u32 cor_mask;
243 	u32 cap_control;
244 	u32 header_log[16];
245 };
246 
247 struct cxl_cper_prot_err_work_data {
248 	struct cxl_cper_sec_prot_err prot_err;
249 	struct cxl_ras_capability_regs ras_cap;
250 	int severity;
251 };
252 
253 #ifdef CONFIG_ACPI_APEI_GHES
254 int cxl_cper_register_work(struct work_struct *work);
255 int cxl_cper_unregister_work(struct work_struct *work);
256 int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd);
257 int cxl_cper_register_prot_err_work(struct work_struct *work);
258 int cxl_cper_unregister_prot_err_work(struct work_struct *work);
259 int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd);
260 #else
cxl_cper_register_work(struct work_struct * work)261 static inline int cxl_cper_register_work(struct work_struct *work)
262 {
263 	return 0;
264 }
265 
cxl_cper_unregister_work(struct work_struct * work)266 static inline int cxl_cper_unregister_work(struct work_struct *work)
267 {
268 	return 0;
269 }
cxl_cper_kfifo_get(struct cxl_cper_work_data * wd)270 static inline int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd)
271 {
272 	return 0;
273 }
cxl_cper_register_prot_err_work(struct work_struct * work)274 static inline int cxl_cper_register_prot_err_work(struct work_struct *work)
275 {
276 	return 0;
277 }
cxl_cper_unregister_prot_err_work(struct work_struct * work)278 static inline int cxl_cper_unregister_prot_err_work(struct work_struct *work)
279 {
280 	return 0;
281 }
cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data * wd)282 static inline int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd)
283 {
284 	return 0;
285 }
286 #endif
287 
288 #endif /* _LINUX_CXL_EVENT_H */
289