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 261 static inline int cxl_cper_register_work(struct work_struct *work) 262 { 263 return 0; 264 } 265 266 static inline int cxl_cper_unregister_work(struct work_struct *work) 267 { 268 return 0; 269 } 270 static inline int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd) 271 { 272 return 0; 273 } 274 static inline int cxl_cper_register_prot_err_work(struct work_struct *work) 275 { 276 return 0; 277 } 278 static inline int cxl_cper_unregister_prot_err_work(struct work_struct *work) 279 { 280 return 0; 281 } 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