Commit | Line | Data |
---|---|---|
6c2b374d ZY |
1 | /* |
2 | * drivers/pci/pcie/aer/aerdrv_errprint.c | |
3 | * | |
4 | * This file is subject to the terms and conditions of the GNU General Public | |
5 | * License. See the file "COPYING" in the main directory of this archive | |
6 | * for more details. | |
7 | * | |
8 | * Format error messages and print them to console. | |
9 | * | |
10 | * Copyright (C) 2006 Intel Corp. | |
11 | * Tom Long Nguyen (tom.l.nguyen@intel.com) | |
12 | * Zhang Yanmin (yanmin.zhang@intel.com) | |
13 | * | |
14 | */ | |
15 | ||
16 | #include <linux/module.h> | |
17 | #include <linux/pci.h> | |
18 | #include <linux/kernel.h> | |
19 | #include <linux/errno.h> | |
20 | #include <linux/pm.h> | |
21 | #include <linux/suspend.h> | |
c413d768 | 22 | #include <linux/cper.h> |
6c2b374d ZY |
23 | |
24 | #include "aerdrv.h" | |
25 | ||
1d521000 LO |
26 | #define CREATE_TRACE_POINTS |
27 | #include <trace/events/ras.h> | |
28 | ||
6c2b374d ZY |
29 | #define AER_AGENT_RECEIVER 0 |
30 | #define AER_AGENT_REQUESTER 1 | |
31 | #define AER_AGENT_COMPLETER 2 | |
32 | #define AER_AGENT_TRANSMITTER 3 | |
33 | ||
f1585756 HS |
34 | #define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \ |
35 | 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP)) | |
36 | #define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \ | |
37 | 0 : PCI_ERR_UNC_COMP_ABORT) | |
38 | #define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \ | |
39 | (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0) | |
6c2b374d ZY |
40 | |
41 | #define AER_GET_AGENT(t, e) \ | |
f1585756 HS |
42 | ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \ |
43 | (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \ | |
44 | (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \ | |
6c2b374d ZY |
45 | AER_AGENT_RECEIVER) |
46 | ||
6c2b374d ZY |
47 | #define AER_PHYSICAL_LAYER_ERROR 0 |
48 | #define AER_DATA_LINK_LAYER_ERROR 1 | |
49 | #define AER_TRANSACTION_LAYER_ERROR 2 | |
50 | ||
f1585756 HS |
51 | #define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \ |
52 | PCI_ERR_COR_RCVR : 0) | |
53 | #define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \ | |
54 | (PCI_ERR_COR_BAD_TLP| \ | |
55 | PCI_ERR_COR_BAD_DLLP| \ | |
56 | PCI_ERR_COR_REP_ROLL| \ | |
57 | PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP) | |
58 | ||
59 | #define AER_GET_LAYER_ERROR(t, e) \ | |
60 | ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \ | |
61 | (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \ | |
62 | AER_TRANSACTION_LAYER_ERROR) | |
6c2b374d ZY |
63 | |
64 | /* | |
65 | * AER error strings | |
66 | */ | |
b64a4414 | 67 | static const char *aer_error_severity_string[] = { |
6c2b374d ZY |
68 | "Uncorrected (Non-Fatal)", |
69 | "Uncorrected (Fatal)", | |
70 | "Corrected" | |
71 | }; | |
72 | ||
b64a4414 | 73 | static const char *aer_error_layer[] = { |
6c2b374d ZY |
74 | "Physical Layer", |
75 | "Data Link Layer", | |
76 | "Transaction Layer" | |
77 | }; | |
b64a4414 HY |
78 | |
79 | static const char *aer_correctable_error_string[] = { | |
80 | "Receiver Error", /* Bit Position 0 */ | |
6c2b374d ZY |
81 | NULL, |
82 | NULL, | |
83 | NULL, | |
84 | NULL, | |
85 | NULL, | |
b64a4414 HY |
86 | "Bad TLP", /* Bit Position 6 */ |
87 | "Bad DLLP", /* Bit Position 7 */ | |
88 | "RELAY_NUM Rollover", /* Bit Position 8 */ | |
6c2b374d ZY |
89 | NULL, |
90 | NULL, | |
91 | NULL, | |
b64a4414 HY |
92 | "Replay Timer Timeout", /* Bit Position 12 */ |
93 | "Advisory Non-Fatal", /* Bit Position 13 */ | |
6c2b374d ZY |
94 | }; |
95 | ||
b64a4414 | 96 | static const char *aer_uncorrectable_error_string[] = { |
6c2b374d ZY |
97 | NULL, |
98 | NULL, | |
99 | NULL, | |
100 | NULL, | |
b64a4414 | 101 | "Data Link Protocol", /* Bit Position 4 */ |
6c2b374d ZY |
102 | NULL, |
103 | NULL, | |
104 | NULL, | |
105 | NULL, | |
106 | NULL, | |
107 | NULL, | |
108 | NULL, | |
b64a4414 HY |
109 | "Poisoned TLP", /* Bit Position 12 */ |
110 | "Flow Control Protocol", /* Bit Position 13 */ | |
111 | "Completion Timeout", /* Bit Position 14 */ | |
112 | "Completer Abort", /* Bit Position 15 */ | |
113 | "Unexpected Completion", /* Bit Position 16 */ | |
114 | "Receiver Overflow", /* Bit Position 17 */ | |
115 | "Malformed TLP", /* Bit Position 18 */ | |
116 | "ECRC", /* Bit Position 19 */ | |
117 | "Unsupported Request", /* Bit Position 20 */ | |
6c2b374d ZY |
118 | }; |
119 | ||
b64a4414 | 120 | static const char *aer_agent_string[] = { |
6c2b374d ZY |
121 | "Receiver ID", |
122 | "Requester ID", | |
123 | "Completer ID", | |
124 | "Transmitter ID" | |
125 | }; | |
126 | ||
fab4c256 BP |
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 | ||
2cced2d9 | 142 | static void __aer_print_error(struct pci_dev *dev, |
b64a4414 | 143 | struct aer_err_info *info) |
6c2b374d | 144 | { |
0d90c3ac | 145 | int i, status; |
b64a4414 | 146 | const char *errmsg = NULL; |
0d90c3ac HS |
147 | status = (info->status & ~info->mask); |
148 | ||
6c2b374d | 149 | for (i = 0; i < 32; i++) { |
0d90c3ac | 150 | if (!(status & (1 << i))) |
6c2b374d ZY |
151 | continue; |
152 | ||
24dbb7be | 153 | if (info->severity == AER_CORRECTABLE) |
b64a4414 HY |
154 | errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ? |
155 | aer_correctable_error_string[i] : NULL; | |
6c2b374d | 156 | else |
b64a4414 HY |
157 | errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ? |
158 | aer_uncorrectable_error_string[i] : NULL; | |
6c2b374d | 159 | |
24dbb7be | 160 | if (errmsg) |
2cced2d9 | 161 | dev_err(&dev->dev, " [%2d] %-22s%s\n", i, errmsg, |
79e4b89b | 162 | info->first_error == i ? " (First)" : ""); |
24dbb7be | 163 | else |
2cced2d9 LO |
164 | dev_err(&dev->dev, " [%2d] Unknown Error Bit%s\n", |
165 | i, info->first_error == i ? " (First)" : ""); | |
6c2b374d | 166 | } |
6c2b374d ZY |
167 | } |
168 | ||
6c2b374d ZY |
169 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) |
170 | { | |
1c38108a | 171 | int layer, agent; |
0d465f23 | 172 | int id = ((dev->bus->number << 8) | dev->devfn); |
6c2b374d | 173 | |
1c38108a | 174 | if (!info->status) { |
227f0647 | 175 | dev_err(&dev->dev, "PCIe Bus Error: severity=%s, type=Unaccessible, id=%04x(Unregistered Agent ID)\n", |
79e4b89b | 176 | aer_error_severity_string[info->severity], id); |
1c38108a BP |
177 | goto out; |
178 | } | |
6c2b374d | 179 | |
1c38108a BP |
180 | layer = AER_GET_LAYER_ERROR(info->severity, info->status); |
181 | agent = AER_GET_AGENT(info->severity, info->status); | |
6c2b374d | 182 | |
227f0647 | 183 | dev_err(&dev->dev, "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", |
1c38108a BP |
184 | aer_error_severity_string[info->severity], |
185 | aer_error_layer[layer], id, aer_agent_string[agent]); | |
79e4b89b | 186 | |
227f0647 | 187 | dev_err(&dev->dev, " device [%04x:%04x] error status/mask=%08x/%08x\n", |
1c38108a BP |
188 | dev->vendor, dev->device, |
189 | info->status, info->mask); | |
79e4b89b | 190 | |
1c38108a | 191 | __aer_print_error(dev, info); |
6c2b374d | 192 | |
1c38108a BP |
193 | if (info->tlp_header_valid) |
194 | __print_tlp_header(dev, &info->tlp); | |
0d465f23 | 195 | |
1c38108a | 196 | out: |
0d465f23 | 197 | if (info->id && info->error_dev_num > 1 && info->id == id) |
1c38108a BP |
198 | dev_err(&dev->dev, " Error of this Agent(%04x) is reported first\n", id); |
199 | ||
1d521000 LO |
200 | trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask), |
201 | info->severity); | |
79e4b89b HS |
202 | } |
203 | ||
204 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) | |
205 | { | |
206 | dev_info(&dev->dev, "AER: %s%s error received: id=%04x\n", | |
207 | info->multi_error_valid ? "Multiple " : "", | |
208 | aer_error_severity_string[info->severity], info->id); | |
6c2b374d | 209 | } |
c413d768 HY |
210 | |
211 | #ifdef CONFIG_ACPI_APEI_PCIEAER | |
0918472c | 212 | int cper_severity_to_aer(int cper_severity) |
c413d768 HY |
213 | { |
214 | switch (cper_severity) { | |
215 | case CPER_SEV_RECOVERABLE: | |
216 | return AER_NONFATAL; | |
217 | case CPER_SEV_FATAL: | |
218 | return AER_FATAL; | |
219 | default: | |
220 | return AER_CORRECTABLE; | |
221 | } | |
222 | } | |
0918472c | 223 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); |
c413d768 | 224 | |
37448adf | 225 | void cper_print_aer(struct pci_dev *dev, int cper_severity, |
c413d768 HY |
226 | struct aer_capability_regs *aer) |
227 | { | |
228 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; | |
229 | u32 status, mask; | |
230 | const char **status_strs; | |
231 | ||
232 | aer_severity = cper_severity_to_aer(cper_severity); | |
1c38108a | 233 | |
c413d768 HY |
234 | if (aer_severity == AER_CORRECTABLE) { |
235 | status = aer->cor_status; | |
236 | mask = aer->cor_mask; | |
237 | status_strs = aer_correctable_error_string; | |
238 | status_strs_size = ARRAY_SIZE(aer_correctable_error_string); | |
239 | } else { | |
240 | status = aer->uncor_status; | |
241 | mask = aer->uncor_mask; | |
242 | status_strs = aer_uncorrectable_error_string; | |
243 | status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); | |
244 | tlp_header_valid = status & AER_LOG_TLP_MASKS; | |
245 | } | |
1c38108a | 246 | |
c413d768 HY |
247 | layer = AER_GET_LAYER_ERROR(aer_severity, status); |
248 | agent = AER_GET_AGENT(aer_severity, status); | |
1c38108a BP |
249 | |
250 | dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask); | |
37448adf | 251 | cper_print_bits("", status, status_strs, status_strs_size); |
2cced2d9 | 252 | dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", |
1c38108a BP |
253 | aer_error_layer[layer], aer_agent_string[agent]); |
254 | ||
c413d768 | 255 | if (aer_severity != AER_CORRECTABLE) |
2cced2d9 | 256 | dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", |
1c38108a | 257 | aer->uncor_severity); |
fab4c256 BP |
258 | |
259 | if (tlp_header_valid) | |
260 | __print_tlp_header(dev, &aer->header_log); | |
261 | ||
1d521000 LO |
262 | trace_aer_event(dev_name(&dev->dev), (status & ~mask), |
263 | aer_severity); | |
c413d768 HY |
264 | } |
265 | #endif |