|
12 | 12 | #include <linux/ratelimit.h> |
13 | 13 | #include <linux/edac.h> |
14 | 14 | #include <linux/ras.h> |
| 15 | +#include <cxl/event.h> |
15 | 16 | #include <acpi/ghes.h> |
16 | 17 | #include <asm/cpu.h> |
17 | 18 | #include <asm/mce.h> |
@@ -132,6 +133,53 @@ static int print_extlog_rcd(const char *pfx, |
132 | 133 | return 1; |
133 | 134 | } |
134 | 135 |
|
| 136 | +static void extlog_print_pcie(struct cper_sec_pcie *pcie_err, |
| 137 | + int severity) |
| 138 | +{ |
| 139 | +#ifdef ACPI_APEI_PCIEAER |
| 140 | + struct aer_capability_regs *aer; |
| 141 | + struct pci_dev *pdev; |
| 142 | + unsigned int devfn; |
| 143 | + unsigned int bus; |
| 144 | + int aer_severity; |
| 145 | + int domain; |
| 146 | + |
| 147 | + if (!(pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID && |
| 148 | + pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO)) |
| 149 | + return; |
| 150 | + |
| 151 | + aer_severity = cper_severity_to_aer(severity); |
| 152 | + aer = (struct aer_capability_regs *)pcie_err->aer_info; |
| 153 | + domain = pcie_err->device_id.segment; |
| 154 | + bus = pcie_err->device_id.bus; |
| 155 | + devfn = PCI_DEVFN(pcie_err->device_id.device, |
| 156 | + pcie_err->device_id.function); |
| 157 | + pdev = pci_get_domain_bus_and_slot(domain, bus, devfn); |
| 158 | + if (!pdev) |
| 159 | + return; |
| 160 | + |
| 161 | + pci_print_aer(pdev, aer_severity, aer); |
| 162 | + pci_dev_put(pdev); |
| 163 | +#endif |
| 164 | +} |
| 165 | + |
| 166 | +static void |
| 167 | +extlog_cxl_cper_handle_prot_err(struct cxl_cper_sec_prot_err *prot_err, |
| 168 | + int severity) |
| 169 | +{ |
| 170 | +#ifdef ACPI_APEI_PCIEAER |
| 171 | + struct cxl_cper_prot_err_work_data wd; |
| 172 | + |
| 173 | + if (cxl_cper_sec_prot_err_valid(prot_err)) |
| 174 | + return; |
| 175 | + |
| 176 | + if (cxl_cper_setup_prot_err_work_data(&wd, prot_err, severity)) |
| 177 | + return; |
| 178 | + |
| 179 | + cxl_cper_handle_prot_err(&wd); |
| 180 | +#endif |
| 181 | +} |
| 182 | + |
135 | 183 | static int extlog_print(struct notifier_block *nb, unsigned long val, |
136 | 184 | void *data) |
137 | 185 | { |
@@ -183,6 +231,22 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, |
183 | 231 | if (gdata->error_data_length >= sizeof(*mem)) |
184 | 232 | trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, |
185 | 233 | (u8)gdata->error_severity); |
| 234 | + } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) { |
| 235 | + struct cxl_cper_sec_prot_err *prot_err = |
| 236 | + acpi_hest_get_payload(gdata); |
| 237 | + |
| 238 | + extlog_cxl_cper_handle_prot_err(prot_err, |
| 239 | + gdata->error_severity); |
| 240 | + } else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { |
| 241 | + struct cper_sec_pcie *pcie_err = acpi_hest_get_payload(gdata); |
| 242 | + |
| 243 | + extlog_print_pcie(pcie_err, gdata->error_severity); |
| 244 | + } else { |
| 245 | + void *err = acpi_hest_get_payload(gdata); |
| 246 | + |
| 247 | + log_non_standard_event(sec_type, fru_id, fru_text, |
| 248 | + gdata->error_severity, err, |
| 249 | + gdata->error_data_length); |
186 | 250 | } |
187 | 251 | } |
188 | 252 |
|
|
0 commit comments