ACPI, APEI, Add PCIe AER error information printing support
[pandora-kernel.git] / drivers / pci / pcie / aer / aerdrv_errprint.c
index 7a237f6..b07a42e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
+#include <linux/cper.h>
 
 #include "aerdrv.h"
 
@@ -201,3 +202,61 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
                info->multi_error_valid ? "Multiple " : "",
                aer_error_severity_string[info->severity], info->id);
 }
+
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+static int cper_severity_to_aer(int cper_severity)
+{
+       switch (cper_severity) {
+       case CPER_SEV_RECOVERABLE:
+               return AER_NONFATAL;
+       case CPER_SEV_FATAL:
+               return AER_FATAL;
+       default:
+               return AER_CORRECTABLE;
+       }
+}
+
+void cper_print_aer(const char *prefix, int cper_severity,
+                   struct aer_capability_regs *aer)
+{
+       int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
+       u32 status, mask;
+       const char **status_strs;
+
+       aer_severity = cper_severity_to_aer(cper_severity);
+       if (aer_severity == AER_CORRECTABLE) {
+               status = aer->cor_status;
+               mask = aer->cor_mask;
+               status_strs = aer_correctable_error_string;
+               status_strs_size = ARRAY_SIZE(aer_correctable_error_string);
+       } else {
+               status = aer->uncor_status;
+               mask = aer->uncor_mask;
+               status_strs = aer_uncorrectable_error_string;
+               status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);
+               tlp_header_valid = status & AER_LOG_TLP_MASKS;
+       }
+       layer = AER_GET_LAYER_ERROR(aer_severity, status);
+       agent = AER_GET_AGENT(aer_severity, status);
+       printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n",
+              prefix, status, mask);
+       cper_print_bits(prefix, status, status_strs, status_strs_size);
+       printk("%s""aer_layer=%s, aer_agent=%s\n", prefix,
+              aer_error_layer[layer], aer_agent_string[agent]);
+       if (aer_severity != AER_CORRECTABLE)
+               printk("%s""aer_uncor_severity: 0x%08x\n",
+                      prefix, aer->uncor_severity);
+       if (tlp_header_valid) {
+               const unsigned char *tlp;
+               tlp = (const unsigned char *)&aer->header_log;
+               printk("%s""aer_tlp_header:"
+                       " %02x%02x%02x%02x %02x%02x%02x%02x"
+                       " %02x%02x%02x%02x %02x%02x%02x%02x\n",
+                       prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+                       *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
+                       *(tlp + 11), *(tlp + 10), *(tlp + 9),
+                       *(tlp + 8), *(tlp + 15), *(tlp + 14),
+                       *(tlp + 13), *(tlp + 12));
+       }
+}
+#endif