aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2013-06-07 16:24:00 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-06-07 16:24:00 -0400
commit5899309c90971d5418abc4bf370bee871ff6072c (patch)
tree331b7922d0f3995110e130aa731dd7b2fbfea135 /drivers
parentbb4bac9308bf8df5027dcbf27f1016104e3a504f (diff)
parent081d0fe0ef60c258b67428a8fdf2d14f8ce392ef (diff)
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
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/apei/ghes.c10
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h4
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c47
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c17
4 files changed, 43 insertions, 35 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
32static 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
32struct aer_hest_parse_info { 48struct 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
90int pcie_aer_get_firmware_first(struct pci_dev *dev) 88int 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 */
408static pci_ers_result_t default_downstream_reset_link(struct pci_dev *dev) 409static 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",