aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 63e23062e982..b58ed05078b8 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -100,6 +100,9 @@ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
static DEFINE_SPINLOCK(slot_errbuf_lock);
static int eeh_error_buf_size;
+#define EEH_PCI_REGS_LOG_LEN 4096
+static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
+
/* System monitoring statistics */
static unsigned long no_device;
static unsigned long no_dn;
@@ -115,7 +118,8 @@ static unsigned long slot_resets;
/* --------------------------------------------------------------- */
/* Below lies the EEH event infrastructure */
-void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
+static void rtas_slot_error_detail(struct pci_dn *pdn, int severity,
+ char *driver_log, size_t loglen)
{
int config_addr;
unsigned long flags;
@@ -133,7 +137,8 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
rc = rtas_call(ibm_slot_error_detail,
8, 1, NULL, config_addr,
BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid), NULL, 0,
+ BUID_LO(pdn->phb->buid),
+ virt_to_phys(driver_log), loglen,
virt_to_phys(slot_errbuf),
eeh_error_buf_size,
severity);
@@ -144,6 +149,40 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
}
/**
+ * gather_pci_data - copy assorted PCI config space registers to buff
+ * @pdn: device to report data for
+ * @buf: point to buffer in which to log
+ * @len: amount of room in buffer
+ *
+ * This routine captures assorted PCI configuration space data,
+ * and puts them into a buffer for RTAS error logging.
+ */
+static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
+{
+ u32 cfg;
+ int n = 0;
+
+ n += scnprintf(buf+n, len-n, "%s\n", pdn->node->name);
+ rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg);
+ n += scnprintf(buf+n, len-n, "dev/vend:%x\n", cfg);
+ rtas_read_config(pdn, PCI_COMMAND, 4, &cfg);
+ n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
+
+ return n;
+}
+
+void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
+{
+ size_t loglen = 0;
+ memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN);
+
+ rtas_pci_enable(pdn, EEH_THAW_MMIO);
+ loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
+
+ rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen);
+}
+
+/**
* read_slot_reset_state - Read the reset state of a device node's slot
* @dn: device node to read
* @rets: array to return results in