1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2026 Intel Corporation 4 */ 5 6 #include "xe_device.h" 7 #include "xe_drm_ras.h" 8 #include "xe_pm.h" 9 #include "xe_printk.h" 10 #include "xe_ras.h" 11 #include "xe_ras_types.h" 12 #include "xe_sysctrl.h" 13 #include "xe_sysctrl_event_types.h" 14 #include "xe_sysctrl_mailbox.h" 15 #include "xe_sysctrl_mailbox_types.h" 16 17 /* Severity of detected errors */ 18 enum xe_ras_severity { 19 XE_RAS_SEV_NOT_SUPPORTED = 0, 20 XE_RAS_SEV_CORRECTABLE, 21 XE_RAS_SEV_UNCORRECTABLE, 22 XE_RAS_SEV_INFORMATIONAL, 23 XE_RAS_SEV_MAX 24 }; 25 26 /* Major IP blocks/components where errors can originate */ 27 enum xe_ras_component { 28 XE_RAS_COMP_NOT_SUPPORTED = 0, 29 XE_RAS_COMP_DEVICE_MEMORY, 30 XE_RAS_COMP_CORE_COMPUTE, 31 XE_RAS_COMP_RESERVED, 32 XE_RAS_COMP_PCIE, 33 XE_RAS_COMP_FABRIC, 34 XE_RAS_COMP_SOC_INTERNAL, 35 XE_RAS_COMP_MAX 36 }; 37 38 /* RAS response status codes */ 39 enum xe_ras_response_status { 40 XE_RAS_STATUS_SUCCESS = 0, 41 XE_RAS_STATUS_INVALID_PARAM, 42 XE_RAS_STATUS_OP_NOT_SUPPORTED, 43 XE_RAS_STATUS_TIMEOUT, 44 XE_RAS_STATUS_HARDWARE_FAILURE, 45 XE_RAS_STATUS_INSUFFICIENT_RESOURCES, 46 XE_RAS_STATUS_MAX 47 }; 48 49 static const char *const xe_ras_severities[] = { 50 [XE_RAS_SEV_NOT_SUPPORTED] = "Not Supported", 51 [XE_RAS_SEV_CORRECTABLE] = "Correctable Error", 52 [XE_RAS_SEV_UNCORRECTABLE] = "Uncorrectable Error", 53 [XE_RAS_SEV_INFORMATIONAL] = "Informational Error", 54 }; 55 static_assert(ARRAY_SIZE(xe_ras_severities) == XE_RAS_SEV_MAX); 56 57 static const char *const xe_ras_components[] = { 58 [XE_RAS_COMP_NOT_SUPPORTED] = "Not Supported", 59 [XE_RAS_COMP_DEVICE_MEMORY] = "Device Memory", 60 [XE_RAS_COMP_CORE_COMPUTE] = "Core Compute", 61 [XE_RAS_COMP_RESERVED] = "Reserved", 62 [XE_RAS_COMP_PCIE] = "PCIe", 63 [XE_RAS_COMP_FABRIC] = "Fabric", 64 [XE_RAS_COMP_SOC_INTERNAL] = "SoC Internal", 65 }; 66 static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX); 67 68 static u8 drm_to_xe_ras_severity(u8 severity) 69 { 70 switch (severity) { 71 case DRM_XE_RAS_ERR_SEV_CORRECTABLE: 72 return XE_RAS_SEV_CORRECTABLE; 73 case DRM_XE_RAS_ERR_SEV_UNCORRECTABLE: 74 return XE_RAS_SEV_UNCORRECTABLE; 75 default: 76 return XE_RAS_SEV_NOT_SUPPORTED; 77 } 78 } 79 80 static u8 drm_to_xe_ras_component(u8 component) 81 { 82 switch (component) { 83 case DRM_XE_RAS_ERR_COMP_CORE_COMPUTE: 84 return XE_RAS_COMP_CORE_COMPUTE; 85 case DRM_XE_RAS_ERR_COMP_SOC_INTERNAL: 86 return XE_RAS_COMP_SOC_INTERNAL; 87 case DRM_XE_RAS_ERR_COMP_DEVICE_MEMORY: 88 return XE_RAS_COMP_DEVICE_MEMORY; 89 case DRM_XE_RAS_ERR_COMP_PCIE: 90 return XE_RAS_COMP_PCIE; 91 case DRM_XE_RAS_ERR_COMP_FABRIC: 92 return XE_RAS_COMP_FABRIC; 93 default: 94 return XE_RAS_COMP_NOT_SUPPORTED; 95 } 96 } 97 98 static int ras_status_to_errno(u32 status) 99 { 100 switch (status) { 101 case XE_RAS_STATUS_SUCCESS: 102 return 0; 103 case XE_RAS_STATUS_INVALID_PARAM: 104 return -EINVAL; 105 case XE_RAS_STATUS_OP_NOT_SUPPORTED: 106 return -EOPNOTSUPP; 107 case XE_RAS_STATUS_TIMEOUT: 108 return -ETIMEDOUT; 109 case XE_RAS_STATUS_HARDWARE_FAILURE: 110 return -EIO; 111 case XE_RAS_STATUS_INSUFFICIENT_RESOURCES: 112 return -ENOSPC; 113 default: 114 return -EPROTO; 115 } 116 } 117 118 static inline const char *sev_to_str(u8 severity) 119 { 120 if (severity >= XE_RAS_SEV_MAX) 121 severity = XE_RAS_SEV_NOT_SUPPORTED; 122 123 return xe_ras_severities[severity]; 124 } 125 126 static inline const char *comp_to_str(u8 component) 127 { 128 if (component >= XE_RAS_COMP_MAX) 129 component = XE_RAS_COMP_NOT_SUPPORTED; 130 131 return xe_ras_components[component]; 132 } 133 134 static struct pci_dev *find_usp_dev(struct pci_dev *pdev) 135 { 136 struct pci_dev *vsp; 137 138 /* 139 * Device Hierarchy: 140 * 141 * Upstream Switch Port (USP) --> Virtual Switch Port (VSP) --> SGunit (GPU endpoint) 142 */ 143 vsp = pci_upstream_bridge(pdev); 144 if (!vsp) 145 return NULL; 146 147 return pci_upstream_bridge(vsp); 148 } 149 150 static void ras_usp_aer_init(struct xe_device *xe) 151 { 152 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 153 struct pci_dev *usp; 154 u16 aer_cap; 155 u32 status; 156 157 usp = find_usp_dev(pdev); 158 if (!usp) 159 return; 160 161 aer_cap = pci_find_ext_capability(usp, PCI_EXT_CAP_ID_ERR); 162 if (!aer_cap) { 163 dev_warn(&usp->dev, "AER capability unavailable\n"); 164 return; 165 } 166 167 /* 168 * Clear any stale Uncorrectable Internal Error Status event in Uncorrectable Error 169 * Status Register. 170 */ 171 pci_read_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, &status); 172 if (status & PCI_ERR_UNC_INTN) 173 pci_write_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, PCI_ERR_UNC_INTN); 174 175 /* 176 * All errors are steered to USP which is a PCIe AER Compliant device. 177 * Downgrade all the errors to non-fatal to prevent PCIe bus driver 178 * from triggering a Secondary Bus Reset (SBR). This allows error 179 * detection, containment and recovery in the driver. 180 * 181 * The Uncorrectable Error Severity Register has the 'Uncorrectable 182 * Internal Error Severity' set to fatal by default. Set this to 183 * non-fatal and unmask the error. 184 */ 185 186 /* Downgrade Uncorrectable Internal Error to non-fatal */ 187 pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_INTN, 0); 188 189 /* Unmask Uncorrectable Internal Error */ 190 pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_MASK, PCI_ERR_UNC_INTN, 0); 191 192 pci_save_state(usp); 193 dev_dbg(&usp->dev, "Uncorrectable Internal Errors downgraded and unmasked\n"); 194 } 195 196 void xe_ras_counter_threshold_crossed(struct xe_device *xe, 197 struct xe_sysctrl_event_response *response) 198 { 199 struct xe_ras_threshold_crossed *pending = (void *)&response->data; 200 struct xe_ras_error_class *errors = pending->counters; 201 u32 id, ncounters = pending->ncounters; 202 203 BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending)); 204 xe_device_assert_mem_access(xe); 205 206 if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS) 207 xe_err(xe, "sysctrl: unexpected counter threshold crossed %u\n", ncounters); 208 else 209 xe_warn(xe, "[RAS]: counter threshold crossed, %u new errors\n", ncounters); 210 211 for (id = 0; id < ncounters && id < XE_RAS_NUM_COUNTERS; id++) { 212 u8 severity, component; 213 214 severity = errors[id].common.severity; 215 component = errors[id].common.component; 216 217 xe_warn(xe, "[RAS]: %s %s detected\n", 218 comp_to_str(component), sev_to_str(severity)); 219 } 220 } 221 222 static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value) 223 { 224 struct xe_ras_get_counter_response response = {0}; 225 struct xe_ras_get_counter_request request = {0}; 226 struct xe_sysctrl_mailbox_command command = {0}; 227 struct xe_ras_error_common *common; 228 size_t rlen; 229 int ret; 230 231 request.counter = *counter; 232 233 xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_COUNTER, 234 &request, sizeof(request), &response, sizeof(response)); 235 236 ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen); 237 if (ret) { 238 xe_err(xe, "sysctrl: failed to get counter %d\n", ret); 239 return ret; 240 } 241 242 if (rlen != sizeof(response)) { 243 xe_err(xe, "sysctrl: unexpected get counter response length %zu (expected %zu)\n", 244 rlen, sizeof(response)); 245 return -EIO; 246 } 247 248 common = &response.counter.common; 249 *value = response.value; 250 251 xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component), 252 sev_to_str(common->severity)); 253 254 return 0; 255 } 256 257 /** 258 * xe_ras_get_counter() - Get error counter value 259 * @xe: Xe device instance 260 * @severity: Error severity to be queried (&enum drm_xe_ras_error_severity) 261 * @component: Error component to be queried (&enum drm_xe_ras_error_component) 262 * @value: Counter value 263 * 264 * This function retrieves the value of a specific error counter based on 265 * the error severity and component. 266 * 267 * Return: 0 on success, negative error code on failure. 268 */ 269 int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value) 270 { 271 struct xe_ras_error_class counter = {0}; 272 273 counter.common.severity = drm_to_xe_ras_severity(severity); 274 counter.common.component = drm_to_xe_ras_component(component); 275 276 guard(xe_pm_runtime)(xe); 277 return get_counter(xe, &counter, value); 278 } 279 280 /** 281 * xe_ras_clear_counter() - Clear error counter value 282 * @xe: Xe device instance 283 * @severity: Error severity to be cleared (&enum drm_xe_ras_error_severity) 284 * @component: Error component to be cleared (&enum drm_xe_ras_error_component) 285 * 286 * This function clears the value of a specific error counter based on 287 * the error severity and component. 288 * 289 * Return: 0 on success, negative error code on failure. 290 */ 291 int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component) 292 { 293 struct xe_ras_clear_counter_response response = {0}; 294 struct xe_ras_clear_counter_request request = {0}; 295 struct xe_sysctrl_mailbox_command command = {0}; 296 struct xe_ras_error_class *counter; 297 size_t rlen; 298 int ret; 299 300 counter = &request.counter; 301 counter->common.severity = drm_to_xe_ras_severity(severity); 302 counter->common.component = drm_to_xe_ras_component(component); 303 304 xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_CLEAR_COUNTER, 305 &request, sizeof(request), &response, sizeof(response)); 306 307 guard(xe_pm_runtime)(xe); 308 ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen); 309 if (ret) { 310 xe_err(xe, "sysctrl: failed to clear counter %d\n", ret); 311 return ret; 312 } 313 314 if (rlen != sizeof(response)) { 315 xe_err(xe, "sysctrl: unexpected clear counter response length %zu (expected %zu)\n", 316 rlen, sizeof(response)); 317 return -EIO; 318 } 319 320 ret = ras_status_to_errno(response.status); 321 if (ret) { 322 xe_err(xe, "sysctrl: clear counter command failed with status %#x\n", 323 response.status); 324 return ret; 325 } 326 327 counter = &response.counter; 328 329 xe_dbg(xe, "[RAS]: clear counter for %s %s\n", comp_to_str(counter->common.component), 330 sev_to_str(counter->common.severity)); 331 332 return 0; 333 } 334 335 /** 336 * xe_ras_init - Initialize Xe RAS 337 * @xe: xe device instance 338 * 339 * Initialize Xe RAS 340 */ 341 void xe_ras_init(struct xe_device *xe) 342 { 343 if (!xe->info.has_drm_ras) 344 return; 345 346 xe_drm_ras_init(xe); 347 348 if (!xe->info.has_sysctrl) 349 return; 350 351 if (IS_ENABLED(CONFIG_PCIEAER)) 352 ras_usp_aer_init(xe); 353 } 354