diff options
author | Huang Ying <ying.huang@intel.com> | 2011-02-21 00:54:43 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-03-21 22:59:08 -0400 |
commit | c413d7682020a127f54744a1b30f597692aea1fd (patch) | |
tree | b495af23b2f81b6ab0080925aa988ea9a8068e4e /drivers/pci/pcie/aer | |
parent | b64a44146540a4761bb1cf8047fffd9dbf0c3090 (diff) |
ACPI, APEI, Add PCIe AER error information printing support
The AER error information printing support is implemented in
drivers/pci/pcie/aer/aer_print.c. So some string constants, functions
and macros definitions can be re-used without being exported.
The original PCIe AER error information printing function is not
re-used directly because the overall format is quite different. And
changing the original printing format may make some original users'
scripts broken.
Signed-off-by: Huang Ying <ying.huang@intel.com>
CC: Jesse Barnes <jbarnes@virtuousgeek.org>
CC: Zhang Yanmin <yanmin.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci/pcie/aer')
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 9 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_errprint.c | 59 |
2 files changed, 60 insertions, 8 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 80c11d131499..3eb77080366a 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -35,13 +35,6 @@ | |||
35 | PCI_ERR_UNC_UNX_COMP| \ | 35 | PCI_ERR_UNC_UNX_COMP| \ |
36 | PCI_ERR_UNC_MALF_TLP) | 36 | PCI_ERR_UNC_MALF_TLP) |
37 | 37 | ||
38 | struct header_log_regs { | ||
39 | unsigned int dw0; | ||
40 | unsigned int dw1; | ||
41 | unsigned int dw2; | ||
42 | unsigned int dw3; | ||
43 | }; | ||
44 | |||
45 | #define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */ | 38 | #define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */ |
46 | struct aer_err_info { | 39 | struct aer_err_info { |
47 | struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; | 40 | struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES]; |
@@ -59,7 +52,7 @@ struct aer_err_info { | |||
59 | 52 | ||
60 | unsigned int status; /* COR/UNCOR Error Status */ | 53 | unsigned int status; /* COR/UNCOR Error Status */ |
61 | unsigned int mask; /* COR/UNCOR Error Mask */ | 54 | unsigned int mask; /* COR/UNCOR Error Mask */ |
62 | struct header_log_regs tlp; /* TLP Header */ | 55 | struct aer_header_log_regs tlp; /* TLP Header */ |
63 | }; | 56 | }; |
64 | 57 | ||
65 | struct aer_err_source { | 58 | struct aer_err_source { |
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 7a237f67129e..b07a42e0b350 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
22 | #include <linux/cper.h> | ||
22 | 23 | ||
23 | #include "aerdrv.h" | 24 | #include "aerdrv.h" |
24 | 25 | ||
@@ -201,3 +202,61 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) | |||
201 | info->multi_error_valid ? "Multiple " : "", | 202 | info->multi_error_valid ? "Multiple " : "", |
202 | aer_error_severity_string[info->severity], info->id); | 203 | aer_error_severity_string[info->severity], info->id); |
203 | } | 204 | } |
205 | |||
206 | #ifdef CONFIG_ACPI_APEI_PCIEAER | ||
207 | static int cper_severity_to_aer(int cper_severity) | ||
208 | { | ||
209 | switch (cper_severity) { | ||
210 | case CPER_SEV_RECOVERABLE: | ||
211 | return AER_NONFATAL; | ||
212 | case CPER_SEV_FATAL: | ||
213 | return AER_FATAL; | ||
214 | default: | ||
215 | return AER_CORRECTABLE; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | void cper_print_aer(const char *prefix, int cper_severity, | ||
220 | struct aer_capability_regs *aer) | ||
221 | { | ||
222 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; | ||
223 | u32 status, mask; | ||
224 | const char **status_strs; | ||
225 | |||
226 | aer_severity = cper_severity_to_aer(cper_severity); | ||
227 | if (aer_severity == AER_CORRECTABLE) { | ||
228 | status = aer->cor_status; | ||
229 | mask = aer->cor_mask; | ||
230 | status_strs = aer_correctable_error_string; | ||
231 | status_strs_size = ARRAY_SIZE(aer_correctable_error_string); | ||
232 | } else { | ||
233 | status = aer->uncor_status; | ||
234 | mask = aer->uncor_mask; | ||
235 | status_strs = aer_uncorrectable_error_string; | ||
236 | status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); | ||
237 | tlp_header_valid = status & AER_LOG_TLP_MASKS; | ||
238 | } | ||
239 | layer = AER_GET_LAYER_ERROR(aer_severity, status); | ||
240 | agent = AER_GET_AGENT(aer_severity, status); | ||
241 | printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n", | ||
242 | prefix, status, mask); | ||
243 | cper_print_bits(prefix, status, status_strs, status_strs_size); | ||
244 | printk("%s""aer_layer=%s, aer_agent=%s\n", prefix, | ||
245 | aer_error_layer[layer], aer_agent_string[agent]); | ||
246 | if (aer_severity != AER_CORRECTABLE) | ||
247 | printk("%s""aer_uncor_severity: 0x%08x\n", | ||
248 | prefix, aer->uncor_severity); | ||
249 | if (tlp_header_valid) { | ||
250 | const unsigned char *tlp; | ||
251 | tlp = (const unsigned char *)&aer->header_log; | ||
252 | printk("%s""aer_tlp_header:" | ||
253 | " %02x%02x%02x%02x %02x%02x%02x%02x" | ||
254 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
255 | prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | ||
256 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | ||
257 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | ||
258 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | ||
259 | *(tlp + 13), *(tlp + 12)); | ||
260 | } | ||
261 | } | ||
262 | #endif | ||