Merge back APEI material for v4.16.
This commit is contained in:
commit
fd0861952d
|
@ -414,6 +414,51 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCIe AER errors need to be sent to the AER driver for reporting and
|
||||||
|
* recovery. The GHES severities map to the following AER severities and
|
||||||
|
* require the following handling:
|
||||||
|
*
|
||||||
|
* GHES_SEV_CORRECTABLE -> AER_CORRECTABLE
|
||||||
|
* These need to be reported by the AER driver but no recovery is
|
||||||
|
* necessary.
|
||||||
|
* GHES_SEV_RECOVERABLE -> AER_NONFATAL
|
||||||
|
* GHES_SEV_RECOVERABLE && CPER_SEC_RESET -> AER_FATAL
|
||||||
|
* These both need to be reported and recovered from by the AER driver.
|
||||||
|
* GHES_SEV_PANIC does not make it to this handling since the kernel must
|
||||||
|
* panic.
|
||||||
|
*/
|
||||||
|
static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_ACPI_APEI_PCIEAER
|
||||||
|
struct cper_sec_pcie *pcie_err = acpi_hest_get_payload(gdata);
|
||||||
|
|
||||||
|
if (pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
|
||||||
|
pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
|
||||||
|
unsigned int devfn;
|
||||||
|
int aer_severity;
|
||||||
|
|
||||||
|
devfn = PCI_DEVFN(pcie_err->device_id.device,
|
||||||
|
pcie_err->device_id.function);
|
||||||
|
aer_severity = cper_severity_to_aer(gdata->error_severity);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If firmware reset the component to contain
|
||||||
|
* the error, we must reinitialize it before
|
||||||
|
* use, so treat it as a fatal AER error.
|
||||||
|
*/
|
||||||
|
if (gdata->flags & CPER_SEC_RESET)
|
||||||
|
aer_severity = AER_FATAL;
|
||||||
|
|
||||||
|
aer_recover_queue(pcie_err->device_id.segment,
|
||||||
|
pcie_err->device_id.bus,
|
||||||
|
devfn, aer_severity,
|
||||||
|
(struct aer_capability_regs *)
|
||||||
|
pcie_err->aer_info);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void ghes_do_proc(struct ghes *ghes,
|
static void ghes_do_proc(struct ghes *ghes,
|
||||||
const struct acpi_hest_generic_status *estatus)
|
const struct acpi_hest_generic_status *estatus)
|
||||||
{
|
{
|
||||||
|
@ -441,38 +486,9 @@ static void ghes_do_proc(struct ghes *ghes,
|
||||||
arch_apei_report_mem_error(sev, mem_err);
|
arch_apei_report_mem_error(sev, mem_err);
|
||||||
ghes_handle_memory_failure(gdata, sev);
|
ghes_handle_memory_failure(gdata, sev);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_ACPI_APEI_PCIEAER
|
|
||||||
else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
|
else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
|
||||||
struct cper_sec_pcie *pcie_err = acpi_hest_get_payload(gdata);
|
ghes_handle_aer(gdata);
|
||||||
|
|
||||||
if (sev == GHES_SEV_RECOVERABLE &&
|
|
||||||
sec_sev == GHES_SEV_RECOVERABLE &&
|
|
||||||
pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
|
|
||||||
pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
|
|
||||||
unsigned int devfn;
|
|
||||||
int aer_severity;
|
|
||||||
|
|
||||||
devfn = PCI_DEVFN(pcie_err->device_id.device,
|
|
||||||
pcie_err->device_id.function);
|
|
||||||
aer_severity = cper_severity_to_aer(gdata->error_severity);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If firmware reset the component to contain
|
|
||||||
* the error, we must reinitialize it before
|
|
||||||
* use, so treat it as a fatal AER error.
|
|
||||||
*/
|
|
||||||
if (gdata->flags & CPER_SEC_RESET)
|
|
||||||
aer_severity = AER_FATAL;
|
|
||||||
|
|
||||||
aer_recover_queue(pcie_err->device_id.segment,
|
|
||||||
pcie_err->device_id.bus,
|
|
||||||
devfn, aer_severity,
|
|
||||||
(struct aer_capability_regs *)
|
|
||||||
pcie_err->aer_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
|
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
|
||||||
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
|
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
|
||||||
|
|
||||||
|
@ -870,7 +886,6 @@ static void ghes_print_queued_estatus(void)
|
||||||
struct ghes_estatus_node *estatus_node;
|
struct ghes_estatus_node *estatus_node;
|
||||||
struct acpi_hest_generic *generic;
|
struct acpi_hest_generic *generic;
|
||||||
struct acpi_hest_generic_status *estatus;
|
struct acpi_hest_generic_status *estatus;
|
||||||
u32 len, node_len;
|
|
||||||
|
|
||||||
llnode = llist_del_all(&ghes_estatus_llist);
|
llnode = llist_del_all(&ghes_estatus_llist);
|
||||||
/*
|
/*
|
||||||
|
@ -882,8 +897,6 @@ static void ghes_print_queued_estatus(void)
|
||||||
estatus_node = llist_entry(llnode, struct ghes_estatus_node,
|
estatus_node = llist_entry(llnode, struct ghes_estatus_node,
|
||||||
llnode);
|
llnode);
|
||||||
estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
|
estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
|
||||||
len = cper_estatus_len(estatus);
|
|
||||||
node_len = GHES_ESTATUS_NODE_LEN(len);
|
|
||||||
generic = estatus_node->generic;
|
generic = estatus_node->generic;
|
||||||
ghes_print_estatus(NULL, generic, estatus);
|
ghes_print_estatus(NULL, generic, estatus);
|
||||||
llnode = llnode->next;
|
llnode = llnode->next;
|
||||||
|
|
Loading…
Reference in New Issue