Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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;