diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-18 16:01:20 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-18 16:01:20 -0500 |
commit | d9cdfb8705b5b40087a437c3a58cf9dff59a0a46 (patch) | |
tree | 392038fd0acd2c650ebb27facf85a0c0348ec0e1 /drivers/pci/pcie | |
parent | e338e49dbbbdef27b0a570603b60481b3753eddf (diff) | |
parent | 3620437a73b0ba68bac9c4e8d0fc9b809efca521 (diff) |
Merge branch 'pci/aer' into next
* pci/aer:
PCI/AER: Consolidate HEST error source parsers
PCI/AER: Ignore non-PCIe AER error sources in aer_hest_parse()
PCI/AER: Clean up error printing code a bit
PCI/AER: Add a TLP header print helper
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_acpi.c | 48 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_errprint.c | 95 |
2 files changed, 77 insertions, 66 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index cf611ab2193a..4d6991794fa2 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
@@ -50,14 +50,37 @@ struct aer_hest_parse_info { | |||
50 | int firmware_first; | 50 | int firmware_first; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr) | ||
54 | { | ||
55 | if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT || | ||
56 | hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT || | ||
57 | hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE) | ||
58 | return 1; | ||
59 | return 0; | ||
60 | } | ||
61 | |||
53 | static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) | 62 | static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) |
54 | { | 63 | { |
55 | struct aer_hest_parse_info *info = data; | 64 | struct aer_hest_parse_info *info = data; |
56 | struct acpi_hest_aer_common *p; | 65 | struct acpi_hest_aer_common *p; |
57 | int ff; | 66 | int ff; |
58 | 67 | ||
68 | if (!hest_source_is_pcie_aer(hest_hdr)) | ||
69 | return 0; | ||
70 | |||
59 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); | 71 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); |
60 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | 72 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); |
73 | |||
74 | /* | ||
75 | * If no specific device is supplied, determine whether | ||
76 | * FIRMWARE_FIRST is set for *any* PCIe device. | ||
77 | */ | ||
78 | if (!info->pci_dev) { | ||
79 | info->firmware_first |= ff; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | /* Otherwise, check the specific device */ | ||
61 | if (p->flags & ACPI_HEST_GLOBAL) { | 84 | if (p->flags & ACPI_HEST_GLOBAL) { |
62 | if (hest_match_type(hest_hdr, info->pci_dev)) | 85 | if (hest_match_type(hest_hdr, info->pci_dev)) |
63 | info->firmware_first = ff; | 86 | info->firmware_first = ff; |
@@ -97,33 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev) | |||
97 | 120 | ||
98 | static bool aer_firmware_first; | 121 | static bool aer_firmware_first; |
99 | 122 | ||
100 | static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data) | ||
101 | { | ||
102 | struct acpi_hest_aer_common *p; | ||
103 | |||
104 | if (aer_firmware_first) | ||
105 | return 0; | ||
106 | |||
107 | switch (hest_hdr->type) { | ||
108 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
109 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
110 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
111 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); | ||
112 | aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
113 | default: | ||
114 | return 0; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | /** | 123 | /** |
119 | * aer_acpi_firmware_first - Check if APEI should control AER. | 124 | * aer_acpi_firmware_first - Check if APEI should control AER. |
120 | */ | 125 | */ |
121 | bool aer_acpi_firmware_first(void) | 126 | bool aer_acpi_firmware_first(void) |
122 | { | 127 | { |
123 | static bool parsed = false; | 128 | static bool parsed = false; |
129 | struct aer_hest_parse_info info = { | ||
130 | .pci_dev = NULL, /* Check all PCIe devices */ | ||
131 | .firmware_first = 0, | ||
132 | }; | ||
124 | 133 | ||
125 | if (!parsed) { | 134 | if (!parsed) { |
126 | apei_hest_parse(aer_hest_parse_aff, NULL); | 135 | apei_hest_parse(aer_hest_parse, &info); |
136 | aer_firmware_first = info.firmware_first; | ||
127 | parsed = true; | 137 | parsed = true; |
128 | } | 138 | } |
129 | return aer_firmware_first; | 139 | return aer_firmware_first; |
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 2c7c9f5f592c..34ff7026440c 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c | |||
@@ -124,6 +124,21 @@ static const char *aer_agent_string[] = { | |||
124 | "Transmitter ID" | 124 | "Transmitter ID" |
125 | }; | 125 | }; |
126 | 126 | ||
127 | static void __print_tlp_header(struct pci_dev *dev, | ||
128 | struct aer_header_log_regs *t) | ||
129 | { | ||
130 | unsigned char *tlp = (unsigned char *)&t; | ||
131 | |||
132 | dev_err(&dev->dev, " TLP Header:" | ||
133 | " %02x%02x%02x%02x %02x%02x%02x%02x" | ||
134 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
135 | *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | ||
136 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | ||
137 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | ||
138 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | ||
139 | *(tlp + 13), *(tlp + 12)); | ||
140 | } | ||
141 | |||
127 | static void __aer_print_error(struct pci_dev *dev, | 142 | static void __aer_print_error(struct pci_dev *dev, |
128 | struct aer_err_info *info) | 143 | struct aer_err_info *info) |
129 | { | 144 | { |
@@ -153,48 +168,39 @@ static void __aer_print_error(struct pci_dev *dev, | |||
153 | 168 | ||
154 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) | 169 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) |
155 | { | 170 | { |
171 | int layer, agent; | ||
156 | int id = ((dev->bus->number << 8) | dev->devfn); | 172 | int id = ((dev->bus->number << 8) | dev->devfn); |
157 | 173 | ||
158 | if (info->status == 0) { | 174 | if (!info->status) { |
159 | dev_err(&dev->dev, | 175 | dev_err(&dev->dev, |
160 | "PCIe Bus Error: severity=%s, type=Unaccessible, " | 176 | "PCIe Bus Error: severity=%s, type=Unaccessible, " |
161 | "id=%04x(Unregistered Agent ID)\n", | 177 | "id=%04x(Unregistered Agent ID)\n", |
162 | aer_error_severity_string[info->severity], id); | 178 | aer_error_severity_string[info->severity], id); |
163 | } else { | 179 | goto out; |
164 | int layer, agent; | 180 | } |
165 | 181 | ||
166 | layer = AER_GET_LAYER_ERROR(info->severity, info->status); | 182 | layer = AER_GET_LAYER_ERROR(info->severity, info->status); |
167 | agent = AER_GET_AGENT(info->severity, info->status); | 183 | agent = AER_GET_AGENT(info->severity, info->status); |
168 | 184 | ||
169 | dev_err(&dev->dev, | 185 | dev_err(&dev->dev, |
170 | "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", | 186 | "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", |
171 | aer_error_severity_string[info->severity], | 187 | aer_error_severity_string[info->severity], |
172 | aer_error_layer[layer], id, aer_agent_string[agent]); | 188 | aer_error_layer[layer], id, aer_agent_string[agent]); |
173 | 189 | ||
174 | dev_err(&dev->dev, | 190 | dev_err(&dev->dev, |
175 | " device [%04x:%04x] error status/mask=%08x/%08x\n", | 191 | " device [%04x:%04x] error status/mask=%08x/%08x\n", |
176 | dev->vendor, dev->device, | 192 | dev->vendor, dev->device, |
177 | info->status, info->mask); | 193 | info->status, info->mask); |
178 | 194 | ||
179 | __aer_print_error(dev, info); | 195 | __aer_print_error(dev, info); |
180 | |||
181 | if (info->tlp_header_valid) { | ||
182 | unsigned char *tlp = (unsigned char *) &info->tlp; | ||
183 | dev_err(&dev->dev, " TLP Header:" | ||
184 | " %02x%02x%02x%02x %02x%02x%02x%02x" | ||
185 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
186 | *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | ||
187 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | ||
188 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | ||
189 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | ||
190 | *(tlp + 13), *(tlp + 12)); | ||
191 | } | ||
192 | } | ||
193 | 196 | ||
197 | if (info->tlp_header_valid) | ||
198 | __print_tlp_header(dev, &info->tlp); | ||
199 | |||
200 | out: | ||
194 | if (info->id && info->error_dev_num > 1 && info->id == id) | 201 | if (info->id && info->error_dev_num > 1 && info->id == id) |
195 | dev_err(&dev->dev, | 202 | dev_err(&dev->dev, " Error of this Agent(%04x) is reported first\n", id); |
196 | " Error of this Agent(%04x) is reported first\n", | 203 | |
197 | id); | ||
198 | trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask), | 204 | trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask), |
199 | info->severity); | 205 | info->severity); |
200 | } | 206 | } |
@@ -228,6 +234,7 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity, | |||
228 | const char **status_strs; | 234 | const char **status_strs; |
229 | 235 | ||
230 | aer_severity = cper_severity_to_aer(cper_severity); | 236 | aer_severity = cper_severity_to_aer(cper_severity); |
237 | |||
231 | if (aer_severity == AER_CORRECTABLE) { | 238 | if (aer_severity == AER_CORRECTABLE) { |
232 | status = aer->cor_status; | 239 | status = aer->cor_status; |
233 | mask = aer->cor_mask; | 240 | mask = aer->cor_mask; |
@@ -240,28 +247,22 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity, | |||
240 | status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); | 247 | status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); |
241 | tlp_header_valid = status & AER_LOG_TLP_MASKS; | 248 | tlp_header_valid = status & AER_LOG_TLP_MASKS; |
242 | } | 249 | } |
250 | |||
243 | layer = AER_GET_LAYER_ERROR(aer_severity, status); | 251 | layer = AER_GET_LAYER_ERROR(aer_severity, status); |
244 | agent = AER_GET_AGENT(aer_severity, status); | 252 | agent = AER_GET_AGENT(aer_severity, status); |
245 | dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", | 253 | |
246 | status, mask); | 254 | dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask); |
247 | cper_print_bits("", status, status_strs, status_strs_size); | 255 | cper_print_bits("", status, status_strs, status_strs_size); |
248 | dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", | 256 | dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", |
249 | aer_error_layer[layer], aer_agent_string[agent]); | 257 | aer_error_layer[layer], aer_agent_string[agent]); |
258 | |||
250 | if (aer_severity != AER_CORRECTABLE) | 259 | if (aer_severity != AER_CORRECTABLE) |
251 | dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", | 260 | dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", |
252 | aer->uncor_severity); | 261 | aer->uncor_severity); |
253 | if (tlp_header_valid) { | 262 | |
254 | const unsigned char *tlp; | 263 | if (tlp_header_valid) |
255 | tlp = (const unsigned char *)&aer->header_log; | 264 | __print_tlp_header(dev, &aer->header_log); |
256 | dev_err(&dev->dev, "aer_tlp_header:" | 265 | |
257 | " %02x%02x%02x%02x %02x%02x%02x%02x" | ||
258 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
259 | *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | ||
260 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | ||
261 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | ||
262 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | ||
263 | *(tlp + 13), *(tlp + 12)); | ||
264 | } | ||
265 | trace_aer_event(dev_name(&dev->dev), (status & ~mask), | 266 | trace_aer_event(dev_name(&dev->dev), (status & ~mask), |
266 | aer_severity); | 267 | aer_severity); |
267 | } | 268 | } |