diff options
author | Huang Ying <ying.huang@intel.com> | 2010-05-18 02:35:16 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-05-19 22:40:14 -0400 |
commit | affb72c3a8984ba55e055b0a0228c3ea1a056758 (patch) | |
tree | a6d4c9051110c03f9222bde9c3dcea7822f8570c /drivers/pci | |
parent | ea8c071cad789b1919355fc7a67182a5c9994e6b (diff) |
ACPI, APEI, PCIE AER, use general HEST table parsing in AER firmware_first setup
Now, a dedicated HEST tabling parsing code is used for PCIE AER
firmware_first setup. It is rebased on general HEST tabling parsing
code of APEI. The firmware_first setup code is moved from PCI core to
AER driver too, because it is only AER related.
Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Reviewed-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 17 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_acpi.c | 77 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 8 | ||||
-rw-r--r-- | drivers/pci/probe.c | 8 |
4 files changed, 98 insertions, 12 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index bd833ea3ba49..7182c337aef1 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -134,4 +134,21 @@ static inline int aer_osc_setup(struct pcie_device *pciedev) | |||
134 | } | 134 | } |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | #ifdef CONFIG_ACPI_APEI | ||
138 | extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); | ||
139 | #else | ||
140 | static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | ||
141 | { | ||
142 | if (pci_dev->__aer_firmware_first_valid) | ||
143 | return pci_dev->__aer_firmware_first; | ||
144 | return 0; | ||
145 | } | ||
146 | #endif | ||
147 | |||
148 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | ||
149 | int enable) | ||
150 | { | ||
151 | pci_dev->__aer_firmware_first = !!enable; | ||
152 | pci_dev->__aer_firmware_first_valid = 1; | ||
153 | } | ||
137 | #endif /* _AERDRV_H_ */ | 154 | #endif /* _AERDRV_H_ */ |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 04814087658d..f278d7b0d95d 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/pci-acpi.h> | 17 | #include <linux/pci-acpi.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <acpi/apei.h> | ||
19 | #include "aerdrv.h" | 20 | #include "aerdrv.h" |
20 | 21 | ||
21 | /** | 22 | /** |
@@ -53,3 +54,79 @@ int aer_osc_setup(struct pcie_device *pciedev) | |||
53 | 54 | ||
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
57 | |||
58 | #ifdef CONFIG_ACPI_APEI | ||
59 | static inline int hest_match_pci(struct acpi_hest_aer_common *p, | ||
60 | struct pci_dev *pci) | ||
61 | { | ||
62 | return (0 == pci_domain_nr(pci->bus) && | ||
63 | p->bus == pci->bus->number && | ||
64 | p->device == PCI_SLOT(pci->devfn) && | ||
65 | p->function == PCI_FUNC(pci->devfn)); | ||
66 | } | ||
67 | |||
68 | struct aer_hest_parse_info { | ||
69 | struct pci_dev *pci_dev; | ||
70 | int firmware_first; | ||
71 | }; | ||
72 | |||
73 | static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) | ||
74 | { | ||
75 | struct aer_hest_parse_info *info = data; | ||
76 | struct acpi_hest_aer_common *p; | ||
77 | u8 pcie_type = 0; | ||
78 | u8 bridge = 0; | ||
79 | int ff = 0; | ||
80 | |||
81 | switch (hest_hdr->type) { | ||
82 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
83 | pcie_type = PCI_EXP_TYPE_ROOT_PORT; | ||
84 | break; | ||
85 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
86 | pcie_type = PCI_EXP_TYPE_ENDPOINT; | ||
87 | break; | ||
88 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
89 | if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
90 | bridge = 1; | ||
91 | break; | ||
92 | default: | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); | ||
97 | if (p->flags & ACPI_HEST_GLOBAL) { | ||
98 | if ((info->pci_dev->is_pcie && | ||
99 | info->pci_dev->pcie_type == pcie_type) || bridge) | ||
100 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
101 | } else | ||
102 | if (hest_match_pci(p, info->pci_dev)) | ||
103 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
104 | info->firmware_first = ff; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void aer_set_firmware_first(struct pci_dev *pci_dev) | ||
110 | { | ||
111 | int rc; | ||
112 | struct aer_hest_parse_info info = { | ||
113 | .pci_dev = pci_dev, | ||
114 | .firmware_first = 0, | ||
115 | }; | ||
116 | |||
117 | rc = apei_hest_parse(aer_hest_parse, &info); | ||
118 | |||
119 | if (rc) | ||
120 | pci_dev->__aer_firmware_first = 0; | ||
121 | else | ||
122 | pci_dev->__aer_firmware_first = info.firmware_first; | ||
123 | pci_dev->__aer_firmware_first_valid = 1; | ||
124 | } | ||
125 | |||
126 | int pcie_aer_get_firmware_first(struct pci_dev *dev) | ||
127 | { | ||
128 | if (!dev->__aer_firmware_first_valid) | ||
129 | aer_set_firmware_first(dev); | ||
130 | return dev->__aer_firmware_first; | ||
131 | } | ||
132 | #endif | ||
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index aceb04b67b60..586b6713e417 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -36,7 +36,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
36 | u16 reg16 = 0; | 36 | u16 reg16 = 0; |
37 | int pos; | 37 | int pos; |
38 | 38 | ||
39 | if (dev->aer_firmware_first) | 39 | if (pcie_aer_get_firmware_first(dev)) |
40 | return -EIO; | 40 | return -EIO; |
41 | 41 | ||
42 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 42 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); |
@@ -64,7 +64,7 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) | |||
64 | u16 reg16 = 0; | 64 | u16 reg16 = 0; |
65 | int pos; | 65 | int pos; |
66 | 66 | ||
67 | if (dev->aer_firmware_first) | 67 | if (pcie_aer_get_firmware_first(dev)) |
68 | return -EIO; | 68 | return -EIO; |
69 | 69 | ||
70 | pos = pci_pcie_cap(dev); | 70 | pos = pci_pcie_cap(dev); |
@@ -859,7 +859,7 @@ void aer_delete_rootport(struct aer_rpc *rpc) | |||
859 | */ | 859 | */ |
860 | int aer_init(struct pcie_device *dev) | 860 | int aer_init(struct pcie_device *dev) |
861 | { | 861 | { |
862 | if (dev->port->aer_firmware_first) { | 862 | if (pcie_aer_get_firmware_first(dev->port)) { |
863 | dev_printk(KERN_DEBUG, &dev->device, | 863 | dev_printk(KERN_DEBUG, &dev->device, |
864 | "PCIe errors handled by platform firmware.\n"); | 864 | "PCIe errors handled by platform firmware.\n"); |
865 | goto out; | 865 | goto out; |
@@ -873,7 +873,7 @@ out: | |||
873 | if (forceload) { | 873 | if (forceload) { |
874 | dev_printk(KERN_DEBUG, &dev->device, | 874 | dev_printk(KERN_DEBUG, &dev->device, |
875 | "aerdrv forceload requested.\n"); | 875 | "aerdrv forceload requested.\n"); |
876 | dev->port->aer_firmware_first = 0; | 876 | pcie_aer_force_firmware_first(dev->port, 0); |
877 | return 0; | 877 | return 0; |
878 | } | 878 | } |
879 | return -ENXIO; | 879 | return -ENXIO; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c82548afcd5c..f4adba2d1dd3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/pci-aspm.h> | 12 | #include <linux/pci-aspm.h> |
13 | #include <acpi/acpi_hest.h> | ||
14 | #include "pci.h" | 13 | #include "pci.h" |
15 | 14 | ||
16 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ | 15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ |
@@ -904,12 +903,6 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev) | |||
904 | pdev->is_hotplug_bridge = 1; | 903 | pdev->is_hotplug_bridge = 1; |
905 | } | 904 | } |
906 | 905 | ||
907 | static void set_pci_aer_firmware_first(struct pci_dev *pdev) | ||
908 | { | ||
909 | if (acpi_hest_firmware_first_pci(pdev)) | ||
910 | pdev->aer_firmware_first = 1; | ||
911 | } | ||
912 | |||
913 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) | 906 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) |
914 | 907 | ||
915 | /** | 908 | /** |
@@ -939,7 +932,6 @@ int pci_setup_device(struct pci_dev *dev) | |||
939 | dev->multifunction = !!(hdr_type & 0x80); | 932 | dev->multifunction = !!(hdr_type & 0x80); |
940 | dev->error_state = pci_channel_io_normal; | 933 | dev->error_state = pci_channel_io_normal; |
941 | set_pcie_port_type(dev); | 934 | set_pcie_port_type(dev); |
942 | set_pci_aer_firmware_first(dev); | ||
943 | 935 | ||
944 | list_for_each_entry(slot, &dev->bus->slots, list) | 936 | list_for_each_entry(slot, &dev->bus->slots, list) |
945 | if (PCI_SLOT(dev->devfn) == slot->number) | 937 | if (PCI_SLOT(dev->devfn) == slot->number) |