diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-06-07 16:24:00 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-06-07 16:24:00 -0400 |
commit | 5899309c90971d5418abc4bf370bee871ff6072c (patch) | |
tree | 331b7922d0f3995110e130aa731dd7b2fbfea135 /drivers | |
parent | bb4bac9308bf8df5027dcbf27f1016104e3a504f (diff) | |
parent | 081d0fe0ef60c258b67428a8fdf2d14f8ce392ef (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.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 |
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 | ||
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", |