Commit fd086195 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge back APEI material for v4.16.

parents bb82e0b4 24bc8f03
Loading
Loading
Loading
Loading
+46 −33
Original line number Original line Diff line number Diff line
@@ -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;