diff options
| -rw-r--r-- | drivers/acpi/apei/ghes.c | 10 | ||||
| -rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 4 | ||||
| -rw-r--r-- | drivers/pci/pcie/aer/aerdrv_acpi.c | 47 | ||||
| -rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 17 | ||||
| -rw-r--r-- | include/linux/aer.h | 20 |
5 files changed, 55 insertions, 43 deletions
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d668a8ae602b..ab315515908e 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
| @@ -449,9 +449,19 @@ static void ghes_do_proc(struct ghes *ghes, | |||
| 449 | pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) { | 449 | pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) { |
| 450 | unsigned int devfn; | 450 | unsigned int devfn; |
| 451 | int aer_severity; | 451 | int aer_severity; |
| 452 | |||
| 452 | devfn = PCI_DEVFN(pcie_err->device_id.device, | 453 | devfn = PCI_DEVFN(pcie_err->device_id.device, |
| 453 | pcie_err->device_id.function); | 454 | pcie_err->device_id.function); |
| 454 | aer_severity = cper_severity_to_aer(sev); | 455 | aer_severity = cper_severity_to_aer(sev); |
| 456 | |||
| 457 | /* | ||
| 458 | * If firmware reset the component to contain | ||
| 459 | * the error, we must reinitialize it before | ||
| 460 | * use, so treat it as a fatal AER error. | ||
| 461 | */ | ||
| 462 | if (gdata->flags & CPER_SEC_RESET) | ||
| 463 | aer_severity = AER_FATAL; | ||
| 464 | |||
| 455 | aer_recover_queue(pcie_err->device_id.segment, | 465 | aer_recover_queue(pcie_err->device_id.segment, |
| 456 | pcie_err->device_id.bus, | 466 | pcie_err->device_id.bus, |
| 457 | devfn, aer_severity); | 467 | devfn, aer_severity); |
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index d12c77cd6991..90ea3e88041f 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
| @@ -13,10 +13,6 @@ | |||
| 13 | #include <linux/aer.h> | 13 | #include <linux/aer.h> |
| 14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
| 15 | 15 | ||
| 16 | #define AER_NONFATAL 0 | ||
| 17 | #define AER_FATAL 1 | ||
| 18 | #define AER_CORRECTABLE 2 | ||
| 19 | |||
| 20 | #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ | 16 | #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ |
| 21 | PCI_EXP_RTCTL_SENFEE| \ | 17 | PCI_EXP_RTCTL_SENFEE| \ |
| 22 | PCI_EXP_RTCTL_SEFEE) | 18 | PCI_EXP_RTCTL_SEFEE) |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 5194a7d41730..cf611ab2193a 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
| @@ -29,6 +29,22 @@ static inline int hest_match_pci(struct acpi_hest_aer_common *p, | |||
| 29 | p->function == PCI_FUNC(pci->devfn)); | 29 | p->function == PCI_FUNC(pci->devfn)); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | static inline bool hest_match_type(struct acpi_hest_header *hest_hdr, | ||
| 33 | struct pci_dev *dev) | ||
| 34 | { | ||
| 35 | u16 hest_type = hest_hdr->type; | ||
| 36 | u8 pcie_type = pci_pcie_type(dev); | ||
| 37 | |||
| 38 | if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT && | ||
| 39 | pcie_type == PCI_EXP_TYPE_ROOT_PORT) || | ||
| 40 | (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT && | ||
| 41 | pcie_type == PCI_EXP_TYPE_ENDPOINT) || | ||
| 42 | (hest_type == ACPI_HEST_TYPE_AER_BRIDGE && | ||
| 43 | (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)) | ||
| 44 | return true; | ||
| 45 | return false; | ||
| 46 | } | ||
| 47 | |||
| 32 | struct aer_hest_parse_info { | 48 | struct aer_hest_parse_info { |
| 33 | struct pci_dev *pci_dev; | 49 | struct pci_dev *pci_dev; |
| 34 | int firmware_first; | 50 | int firmware_first; |
| @@ -38,34 +54,16 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) | |||
| 38 | { | 54 | { |
| 39 | struct aer_hest_parse_info *info = data; | 55 | struct aer_hest_parse_info *info = data; |
| 40 | struct acpi_hest_aer_common *p; | 56 | struct acpi_hest_aer_common *p; |
| 41 | u8 pcie_type = 0; | 57 | int ff; |
| 42 | u8 bridge = 0; | ||
| 43 | int ff = 0; | ||
| 44 | |||
| 45 | switch (hest_hdr->type) { | ||
| 46 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
| 47 | pcie_type = PCI_EXP_TYPE_ROOT_PORT; | ||
| 48 | break; | ||
| 49 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
| 50 | pcie_type = PCI_EXP_TYPE_ENDPOINT; | ||
| 51 | break; | ||
| 52 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
| 53 | if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
| 54 | bridge = 1; | ||
| 55 | break; | ||
| 56 | default: | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | 58 | ||
| 60 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); | 59 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); |
| 60 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
| 61 | if (p->flags & ACPI_HEST_GLOBAL) { | 61 | if (p->flags & ACPI_HEST_GLOBAL) { |
| 62 | if ((pci_is_pcie(info->pci_dev) && | 62 | if (hest_match_type(hest_hdr, info->pci_dev)) |
| 63 | pci_pcie_type(info->pci_dev) == pcie_type) || bridge) | 63 | info->firmware_first = ff; |
| 64 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
| 65 | } else | 64 | } else |
| 66 | if (hest_match_pci(p, info->pci_dev)) | 65 | if (hest_match_pci(p, info->pci_dev)) |
| 67 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | 66 | info->firmware_first = ff; |
| 68 | info->firmware_first = ff; | ||
| 69 | 67 | ||
| 70 | return 0; | 68 | return 0; |
| 71 | } | 69 | } |
| @@ -89,6 +87,9 @@ static void aer_set_firmware_first(struct pci_dev *pci_dev) | |||
| 89 | 87 | ||
| 90 | int pcie_aer_get_firmware_first(struct pci_dev *dev) | 88 | int pcie_aer_get_firmware_first(struct pci_dev *dev) |
| 91 | { | 89 | { |
| 90 | if (!pci_is_pcie(dev)) | ||
| 91 | return 0; | ||
| 92 | |||
| 92 | if (!dev->__aer_firmware_first_valid) | 93 | if (!dev->__aer_firmware_first_valid) |
| 93 | aer_set_firmware_first(dev); | 94 | aer_set_firmware_first(dev); |
| 94 | return dev->__aer_firmware_first; | 95 | return dev->__aer_firmware_first; |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 8ec8b4f48560..d9e776e69fe8 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
| @@ -400,16 +400,16 @@ void aer_do_secondary_bus_reset(struct pci_dev *dev) | |||
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | /** | 402 | /** |
| 403 | * default_downstream_reset_link - default reset function for Downstream Port | 403 | * default_reset_link - default reset function |
| 404 | * @dev: pointer to downstream port's pci_dev data structure | 404 | * @dev: pointer to pci_dev data structure |
| 405 | * | 405 | * |
| 406 | * Invoked when performing link reset at Downstream Port w/ no aer driver. | 406 | * Invoked when performing link reset on a Downstream Port or a |
| 407 | * Root Port with no aer driver. | ||
| 407 | */ | 408 | */ |
| 408 | static pci_ers_result_t default_downstream_reset_link(struct pci_dev *dev) | 409 | static pci_ers_result_t default_reset_link(struct pci_dev *dev) |
| 409 | { | 410 | { |
| 410 | aer_do_secondary_bus_reset(dev); | 411 | aer_do_secondary_bus_reset(dev); |
| 411 | dev_printk(KERN_DEBUG, &dev->dev, | 412 | dev_printk(KERN_DEBUG, &dev->dev, "downstream link has been reset\n"); |
| 412 | "Downstream Port link has been reset\n"); | ||
| 413 | return PCI_ERS_RESULT_RECOVERED; | 413 | return PCI_ERS_RESULT_RECOVERED; |
| 414 | } | 414 | } |
| 415 | 415 | ||
| @@ -458,8 +458,9 @@ static pci_ers_result_t reset_link(struct pci_dev *dev) | |||
| 458 | 458 | ||
| 459 | if (driver && driver->reset_link) { | 459 | if (driver && driver->reset_link) { |
| 460 | status = driver->reset_link(udev); | 460 | status = driver->reset_link(udev); |
| 461 | } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM) { | 461 | } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM || |
| 462 | status = default_downstream_reset_link(udev); | 462 | pci_pcie_type(udev) == PCI_EXP_TYPE_ROOT_PORT) { |
| 463 | status = default_reset_link(udev); | ||
| 463 | } else { | 464 | } else { |
| 464 | dev_printk(KERN_DEBUG, &dev->dev, | 465 | dev_printk(KERN_DEBUG, &dev->dev, |
| 465 | "no link-reset support at upstream device %s\n", | 466 | "no link-reset support at upstream device %s\n", |
diff --git a/include/linux/aer.h b/include/linux/aer.h index ec10e1b24c1c..55bb3dc4b2db 100644 --- a/include/linux/aer.h +++ b/include/linux/aer.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #ifndef _AER_H_ | 7 | #ifndef _AER_H_ |
| 8 | #define _AER_H_ | 8 | #define _AER_H_ |
| 9 | 9 | ||
| 10 | #define AER_NONFATAL 0 | ||
| 11 | #define AER_FATAL 1 | ||
| 12 | #define AER_CORRECTABLE 2 | ||
| 13 | |||
| 10 | struct aer_header_log_regs { | 14 | struct aer_header_log_regs { |
| 11 | unsigned int dw0; | 15 | unsigned int dw0; |
| 12 | unsigned int dw1; | 16 | unsigned int dw1; |
| @@ -31,9 +35,9 @@ struct aer_capability_regs { | |||
| 31 | 35 | ||
| 32 | #if defined(CONFIG_PCIEAER) | 36 | #if defined(CONFIG_PCIEAER) |
| 33 | /* pci-e port driver needs this function to enable aer */ | 37 | /* pci-e port driver needs this function to enable aer */ |
| 34 | extern int pci_enable_pcie_error_reporting(struct pci_dev *dev); | 38 | int pci_enable_pcie_error_reporting(struct pci_dev *dev); |
| 35 | extern int pci_disable_pcie_error_reporting(struct pci_dev *dev); | 39 | int pci_disable_pcie_error_reporting(struct pci_dev *dev); |
| 36 | extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); | 40 | int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); |
| 37 | #else | 41 | #else |
| 38 | static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) | 42 | static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) |
| 39 | { | 43 | { |
| @@ -49,10 +53,10 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
| 49 | } | 53 | } |
| 50 | #endif | 54 | #endif |
| 51 | 55 | ||
| 52 | extern void cper_print_aer(const char *prefix, struct pci_dev *dev, | 56 | void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity, |
| 53 | int cper_severity, struct aer_capability_regs *aer); | 57 | struct aer_capability_regs *aer); |
| 54 | extern int cper_severity_to_aer(int cper_severity); | 58 | int cper_severity_to_aer(int cper_severity); |
| 55 | extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, | 59 | void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, |
| 56 | int severity); | 60 | int severity); |
| 57 | #endif //_AER_H_ | 61 | #endif //_AER_H_ |
| 58 | 62 | ||
