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

Commit 5899309c authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/betty-aer-v3' into next

* pci/betty-aer-v3:
  PCI/AER: Reset link for devices below Root Port or Downstream Port
  ACPI / APEI: Force fatal AER severity when component has been reset
  PCI/AER: Remove "extern" from function declarations
  PCI/AER: Move AER severity defines to aer.h
  PCI/AER: Set dev->__aer_firmware_first only for matching devices
  PCI/AER: Factor out HEST device type matching
  PCI/AER: Don't parse HEST table for non-PCIe devices
parents bb4bac93 081d0fe0
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -449,9 +449,19 @@ static void ghes_do_proc(struct ghes *ghes,
			    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(sev);

				/*
				 * 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);
+0 −4
Original line number Diff line number Diff line
@@ -13,10 +13,6 @@
#include <linux/aer.h>
#include <linux/interrupt.h>

#define AER_NONFATAL			0
#define AER_FATAL			1
#define AER_CORRECTABLE			2

#define SYSTEM_ERROR_INTR_ON_MESG_MASK	(PCI_EXP_RTCTL_SECEE|	\
					PCI_EXP_RTCTL_SENFEE|	\
					PCI_EXP_RTCTL_SEFEE)
+24 −23
Original line number Diff line number Diff line
@@ -29,6 +29,22 @@ static inline int hest_match_pci(struct acpi_hest_aer_common *p,
		 p->function == PCI_FUNC(pci->devfn));
}

static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
				struct pci_dev *dev)
{
	u16 hest_type = hest_hdr->type;
	u8 pcie_type = pci_pcie_type(dev);

	if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
		pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
	    (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
		pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
	    (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
		(dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
		return true;
	return false;
}

struct aer_hest_parse_info {
	struct pci_dev *pci_dev;
	int firmware_first;
@@ -38,33 +54,15 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
{
	struct aer_hest_parse_info *info = data;
	struct acpi_hest_aer_common *p;
	u8 pcie_type = 0;
	u8 bridge = 0;
	int ff = 0;

	switch (hest_hdr->type) {
	case ACPI_HEST_TYPE_AER_ROOT_PORT:
		pcie_type = PCI_EXP_TYPE_ROOT_PORT;
		break;
	case ACPI_HEST_TYPE_AER_ENDPOINT:
		pcie_type = PCI_EXP_TYPE_ENDPOINT;
		break;
	case ACPI_HEST_TYPE_AER_BRIDGE:
		if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
			bridge = 1;
		break;
	default:
		return 0;
	}
	int ff;

	p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
	if (p->flags & ACPI_HEST_GLOBAL) {
		if ((pci_is_pcie(info->pci_dev) &&
		     pci_pcie_type(info->pci_dev) == pcie_type) || bridge)
	ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
	if (p->flags & ACPI_HEST_GLOBAL) {
		if (hest_match_type(hest_hdr, info->pci_dev))
			info->firmware_first = ff;
	} else
		if (hest_match_pci(p, info->pci_dev))
			ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
			info->firmware_first = ff;

	return 0;
@@ -89,6 +87,9 @@ static void aer_set_firmware_first(struct pci_dev *pci_dev)

int pcie_aer_get_firmware_first(struct pci_dev *dev)
{
	if (!pci_is_pcie(dev))
		return 0;

	if (!dev->__aer_firmware_first_valid)
		aer_set_firmware_first(dev);
	return dev->__aer_firmware_first;
+9 −8
Original line number Diff line number Diff line
@@ -400,16 +400,16 @@ void aer_do_secondary_bus_reset(struct pci_dev *dev)
}

/**
 * default_downstream_reset_link - default reset function for Downstream Port
 * @dev: pointer to downstream port's pci_dev data structure
 * default_reset_link - default reset function
 * @dev: pointer to pci_dev data structure
 *
 * Invoked when performing link reset at Downstream Port w/ no aer driver.
 * Invoked when performing link reset on a Downstream Port or a
 * Root Port with no aer driver.
 */
static pci_ers_result_t default_downstream_reset_link(struct pci_dev *dev)
static pci_ers_result_t default_reset_link(struct pci_dev *dev)
{
	aer_do_secondary_bus_reset(dev);
	dev_printk(KERN_DEBUG, &dev->dev,
		"Downstream Port link has been reset\n");
	dev_printk(KERN_DEBUG, &dev->dev, "downstream link has been reset\n");
	return PCI_ERS_RESULT_RECOVERED;
}

@@ -458,8 +458,9 @@ static pci_ers_result_t reset_link(struct pci_dev *dev)

	if (driver && driver->reset_link) {
		status = driver->reset_link(udev);
	} else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM) {
		status = default_downstream_reset_link(udev);
	} else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM ||
		pci_pcie_type(udev) == PCI_EXP_TYPE_ROOT_PORT) {
		status = default_reset_link(udev);
	} else {
		dev_printk(KERN_DEBUG, &dev->dev,
			"no link-reset support at upstream device %s\n",
+12 −8
Original line number Diff line number Diff line
@@ -7,6 +7,10 @@
#ifndef _AER_H_
#define _AER_H_

#define AER_NONFATAL			0
#define AER_FATAL			1
#define AER_CORRECTABLE			2

struct aer_header_log_regs {
	unsigned int dw0;
	unsigned int dw1;
@@ -31,9 +35,9 @@ struct aer_capability_regs {

#if defined(CONFIG_PCIEAER)
/* pci-e port driver needs this function to enable aer */
extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
int pci_enable_pcie_error_reporting(struct pci_dev *dev);
int pci_disable_pcie_error_reporting(struct pci_dev *dev);
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
#else
static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
{
@@ -49,10 +53,10 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
}
#endif

extern void cper_print_aer(const char *prefix, struct pci_dev *dev,
			   int cper_severity, struct aer_capability_regs *aer);
extern int cper_severity_to_aer(int cper_severity);
extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity,
		    struct aer_capability_regs *aer);
int cper_severity_to_aer(int cper_severity);
void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
		       int severity);
#endif //_AER_H_