summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinas Vepstas <linas@austin.ibm.com>2006-09-22 01:25:56 +0200
committerPaul Mackerras <paulus@samba.org>2006-09-22 07:19:58 +0200
commite102926385b56e593b995ecc433f041b498a49e1 (patch)
tree28426cd50b4cd833a761242b8a7788596e1ddfe0
parent[POWERPC] Include <asm/mmu.h> in arch/powerpc/sysdev/fsl_soc.h for phys_addr_t. (diff)
downloadlinux-e102926385b56e593b995ecc433f041b498a49e1.tar.xz
linux-e102926385b56e593b995ecc433f041b498a49e1.zip
[POWERPC] EEH: Power4 systems sometimes need multiple resets.
On detection of an EEH error, some Power4 systems seem to occasionally want to be reset twice before they report themselves as fully recovered. This patch re-arranges the code to attempt additional resets if the first one doesn't take. Signed-off-by: Linas Vepstas <linas@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 4534886e3b4e..84bc8f7e17ef 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -478,7 +478,7 @@ eeh_slot_availability(struct pci_dn *pdn)
printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
rc, rets[0], rets[1], rets[2]);
- return -1;
+ return -2;
}
/**
@@ -546,11 +546,10 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
BUID_HI(pdn->phb->buid),
BUID_LO(pdn->phb->buid),
state);
- if (rc) {
- printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n",
+ if (rc)
+ printk (KERN_WARNING "EEH: Unable to reset the failed slot,"
+ " (%d) #RST=%d dn=%s\n",
rc, state, pdn->node->full_name);
- return;
- }
}
/**
@@ -560,11 +559,8 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
* Return 0 if success, else a non-zero value.
*/
-int
-rtas_set_slot_reset(struct pci_dn *pdn)
+static void __rtas_set_slot_reset(struct pci_dn *pdn)
{
- int i, rc;
-
rtas_pci_slot_reset (pdn, 1);
/* The PCI bus requires that the reset be held high for at least
@@ -585,17 +581,33 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* up traffic. */
#define PCI_BUS_SETTLE_TIME_MSEC 1800
msleep (PCI_BUS_SETTLE_TIME_MSEC);
+}
+
+int rtas_set_slot_reset(struct pci_dn *pdn)
+{
+ int i, rc;
+
+ __rtas_set_slot_reset(pdn);
/* Now double check with the firmware to make sure the device is
* ready to be used; if not, wait for recovery. */
for (i=0; i<10; i++) {
rc = eeh_slot_availability (pdn);
- if (rc < 0)
- printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name);
if (rc == 0)
return 0;
- if (rc < 0)
+
+ if (rc == -2) {
+ printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n",
+ i, pdn->node->full_name);
+ __rtas_set_slot_reset(pdn);
+ continue;
+ }
+
+ if (rc < 0) {
+ printk (KERN_ERR "EEH: unrecoverable slot failure %s\n",
+ pdn->node->full_name);
return -1;
+ }
msleep (rc+100);
}