aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinas Vepstas <linas@austin.ibm.com>2006-09-21 19:25:56 -0400
committerPaul Mackerras <paulus@samba.org>2006-09-22 01:19:58 -0400
commite102926385b56e593b995ecc433f041b498a49e1 (patch)
tree28426cd50b4cd833a761242b8a7788596e1ddfe0 /arch
parent3d574abd59d49173ac3096a19575a2f7430505be (diff)
[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>
Diffstat (limited to 'arch')
-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)
478 478
479 printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", 479 printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
480 rc, rets[0], rets[1], rets[2]); 480 rc, rets[0], rets[1], rets[2]);
481 return -1; 481 return -2;
482} 482}
483 483
484/** 484/**
@@ -546,11 +546,10 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
546 BUID_HI(pdn->phb->buid), 546 BUID_HI(pdn->phb->buid),
547 BUID_LO(pdn->phb->buid), 547 BUID_LO(pdn->phb->buid),
548 state); 548 state);
549 if (rc) { 549 if (rc)
550 printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n", 550 printk (KERN_WARNING "EEH: Unable to reset the failed slot,"
551 " (%d) #RST=%d dn=%s\n",
551 rc, state, pdn->node->full_name); 552 rc, state, pdn->node->full_name);
552 return;
553 }
554} 553}
555 554
556/** 555/**
@@ -560,11 +559,8 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
560 * Return 0 if success, else a non-zero value. 559 * Return 0 if success, else a non-zero value.
561 */ 560 */
562 561
563int 562static void __rtas_set_slot_reset(struct pci_dn *pdn)
564rtas_set_slot_reset(struct pci_dn *pdn)
565{ 563{
566 int i, rc;
567
568 rtas_pci_slot_reset (pdn, 1); 564 rtas_pci_slot_reset (pdn, 1);
569 565
570 /* The PCI bus requires that the reset be held high for at least 566 /* 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)
585 * up traffic. */ 581 * up traffic. */
586#define PCI_BUS_SETTLE_TIME_MSEC 1800 582#define PCI_BUS_SETTLE_TIME_MSEC 1800
587 msleep (PCI_BUS_SETTLE_TIME_MSEC); 583 msleep (PCI_BUS_SETTLE_TIME_MSEC);
584}
585
586int rtas_set_slot_reset(struct pci_dn *pdn)
587{
588 int i, rc;
589
590 __rtas_set_slot_reset(pdn);
588 591
589 /* Now double check with the firmware to make sure the device is 592 /* Now double check with the firmware to make sure the device is
590 * ready to be used; if not, wait for recovery. */ 593 * ready to be used; if not, wait for recovery. */
591 for (i=0; i<10; i++) { 594 for (i=0; i<10; i++) {
592 rc = eeh_slot_availability (pdn); 595 rc = eeh_slot_availability (pdn);
593 if (rc < 0)
594 printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name);
595 if (rc == 0) 596 if (rc == 0)
596 return 0; 597 return 0;
597 if (rc < 0) 598
599 if (rc == -2) {
600 printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n",
601 i, pdn->node->full_name);
602 __rtas_set_slot_reset(pdn);
603 continue;
604 }
605
606 if (rc < 0) {
607 printk (KERN_ERR "EEH: unrecoverable slot failure %s\n",
608 pdn->node->full_name);
598 return -1; 609 return -1;
610 }
599 611
600 msleep (rc+100); 612 msleep (rc+100);
601 } 613 }