This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / pci / pcie / aer / aerdrv_errprint.c
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
new file mode 100644 (file)
index 0000000..3933d4f
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv_errprint.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Format error messages and print them to console.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+
+#include "aerdrv.h"
+
+#define AER_AGENT_RECEIVER             0
+#define AER_AGENT_REQUESTER            1
+#define AER_AGENT_COMPLETER            2
+#define AER_AGENT_TRANSMITTER          3
+
+#define AER_AGENT_REQUESTER_MASK       (PCI_ERR_UNC_COMP_TIME| \
+                                       PCI_ERR_UNC_UNSUP)
+
+#define AER_AGENT_COMPLETER_MASK       PCI_ERR_UNC_COMP_ABORT
+
+#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \
+       ((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0)))
+
+#define AER_GET_AGENT(t, e)                                            \
+       ((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER :         \
+       (e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER :          \
+       (AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER :    \
+       AER_AGENT_RECEIVER)
+
+#define AER_PHYSICAL_LAYER_ERROR_MASK  PCI_ERR_COR_RCVR
+#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e)   \
+               (PCI_ERR_UNC_DLP|               \
+               PCI_ERR_COR_BAD_TLP|            \
+               PCI_ERR_COR_BAD_DLLP|           \
+               PCI_ERR_COR_REP_ROLL|           \
+               ((t == AER_CORRECTABLE) ?       \
+               PCI_ERR_COR_REP_TIMER: 0))
+
+#define AER_PHYSICAL_LAYER_ERROR       0
+#define AER_DATA_LINK_LAYER_ERROR      1
+#define AER_TRANSACTION_LAYER_ERROR    2
+
+#define AER_GET_LAYER_ERROR(t, e)                              \
+       ((e & AER_PHYSICAL_LAYER_ERROR_MASK) ?                  \
+       AER_PHYSICAL_LAYER_ERROR :                              \
+       (e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ?            \
+               AER_DATA_LINK_LAYER_ERROR :                     \
+               AER_TRANSACTION_LAYER_ERROR)
+
+/*
+ * AER error strings
+ */
+static char* aer_error_severity_string[] = {
+       "Uncorrected (Non-Fatal)",
+       "Uncorrected (Fatal)",
+       "Corrected"
+};
+
+static char* aer_error_layer[] = {
+       "Physical Layer",
+       "Data Link Layer",
+       "Transaction Layer"
+};
+static char* aer_correctable_error_string[] = {
+       "Receiver Error        ",       /* Bit Position 0       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Bad TLP               ",       /* Bit Position 6       */
+       "Bad DLLP              ",       /* Bit Position 7       */
+       "RELAY_NUM Rollover    ",       /* Bit Position 8       */
+       NULL,
+       NULL,
+       NULL,
+       "Replay Timer Timeout  ",       /* Bit Position 12      */
+       "Advisory Non-Fatal    ",       /* Bit Position 13      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_uncorrectable_error_string[] = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Data Link Protocol    ",       /* Bit Position 4       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Poisoned TLP          ",       /* Bit Position 12      */
+       "Flow Control Protocol ",       /* Bit Position 13      */
+       "Completion Timeout    ",       /* Bit Position 14      */
+       "Completer Abort       ",       /* Bit Position 15      */
+       "Unexpected Completion ",       /* Bit Position 16      */
+       "Receiver Overflow     ",       /* Bit Position 17      */
+       "Malformed TLP         ",       /* Bit Position 18      */
+       "ECRC                  ",       /* Bit Position 19      */
+       "Unsupported Request   ",       /* Bit Position 20      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_agent_string[] = {
+       "Receiver ID",
+       "Requester ID",
+       "Completer ID",
+       "Transmitter ID"
+};
+
+static char * aer_get_error_source_name(int severity,
+                       unsigned int status,
+                       char errmsg_buff[])
+{
+       int i;
+       char * errmsg = NULL;
+
+       for (i = 0; i < 32; i++) {
+               if (!(status & (1 << i)))
+                       continue;
+
+               if (severity == AER_CORRECTABLE)
+                       errmsg = aer_correctable_error_string[i];
+               else
+                       errmsg = aer_uncorrectable_error_string[i];
+
+               if (!errmsg) {
+                       sprintf(errmsg_buff, "Unknown Error Bit %2d  ", i);
+                       errmsg = errmsg_buff;
+               }
+
+               break;
+       }
+
+       return errmsg;
+}
+
+static DEFINE_SPINLOCK(logbuf_lock);
+static char errmsg_buff[100];
+void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
+{
+       char * errmsg;
+       int err_layer, agent;
+       char * loglevel;
+
+       if (info->severity == AER_CORRECTABLE)
+               loglevel = KERN_WARNING;
+       else
+               loglevel = KERN_ERR;
+
+       printk("%s+------ PCI-Express Device Error ------+\n", loglevel);
+       printk("%sError Severity\t\t: %s\n", loglevel,
+               aer_error_severity_string[info->severity]);
+
+       if ( info->status == 0) {
+               printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel);
+               printk("%sUnaccessible Received\t: %s\n", loglevel,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               printk("%sUnregistered Agent ID\t: %04x\n", loglevel,
+                       (dev->bus->number << 8) | dev->devfn);
+       } else {
+               err_layer = AER_GET_LAYER_ERROR(info->severity, info->status);
+               printk("%sPCIE Bus Error type\t: %s\n", loglevel,
+                       aer_error_layer[err_layer]);
+
+               spin_lock(&logbuf_lock);
+               errmsg = aer_get_error_source_name(info->severity,
+                               info->status,
+                               errmsg_buff);
+               printk("%s%s\t: %s\n", loglevel, errmsg,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               spin_unlock(&logbuf_lock);
+
+               agent = AER_GET_AGENT(info->severity, info->status);
+               printk("%s%s\t\t: %04x\n", loglevel,
+                       aer_agent_string[agent],
+                       (dev->bus->number << 8) | dev->devfn);
+
+               printk("%sVendorID=%04xh, DeviceID=%04xh,"
+                       " Bus=%02xh, Device=%02xh, Function=%02xh\n",
+                       loglevel,
+                       dev->vendor,
+                       dev->device,
+                       dev->bus->number,
+                       PCI_SLOT(dev->devfn),
+                       PCI_FUNC(dev->devfn));
+
+               if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
+                       unsigned char *tlp = (unsigned char *) &info->tlp;
+                       printk("%sTLB Header:\n", loglevel);
+                       printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
+                               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
+                               loglevel,
+                               *(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));
+               }
+       }
+}
+