aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c99
-rw-r--r--include/asm-powerpc/ppc-pci.h14
2 files changed, 113 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 1fec99d53311..a06c91a4852b 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -17,6 +17,7 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#include <linux/delay.h>
20#include <linux/init.h> 21#include <linux/init.h>
21#include <linux/list.h> 22#include <linux/list.h>
22#include <linux/pci.h> 23#include <linux/pci.h>
@@ -677,6 +678,104 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon
677EXPORT_SYMBOL(eeh_check_failure); 678EXPORT_SYMBOL(eeh_check_failure);
678 679
679/* ------------------------------------------------------------- */ 680/* ------------------------------------------------------------- */
681/* The code below deals with error recovery */
682
683/** Return negative value if a permanent error, else return
684 * a number of milliseconds to wait until the PCI slot is
685 * ready to be used.
686 */
687static int
688eeh_slot_availability(struct pci_dn *pdn)
689{
690 int rc;
691 int rets[3];
692
693 rc = read_slot_reset_state(pdn, rets);
694
695 if (rc) return rc;
696
697 if (rets[1] == 0) return -1; /* EEH is not supported */
698 if (rets[0] == 0) return 0; /* Oll Korrect */
699 if (rets[0] == 5) {
700 if (rets[2] == 0) return -1; /* permanently unavailable */
701 return rets[2]; /* number of millisecs to wait */
702 }
703 return -1;
704}
705
706/** rtas_pci_slot_reset raises/lowers the pci #RST line
707 * state: 1/0 to raise/lower the #RST
708 *
709 * Clear the EEH-frozen condition on a slot. This routine
710 * asserts the PCI #RST line if the 'state' argument is '1',
711 * and drops the #RST line if 'state is '0'. This routine is
712 * safe to call in an interrupt context.
713 *
714 */
715
716static void
717rtas_pci_slot_reset(struct pci_dn *pdn, int state)
718{
719 int rc;
720
721 BUG_ON (pdn==NULL);
722
723 if (!pdn->phb) {
724 printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n",
725 pdn->node->full_name);
726 return;
727 }
728
729 rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
730 pdn->eeh_config_addr,
731 BUID_HI(pdn->phb->buid),
732 BUID_LO(pdn->phb->buid),
733 state);
734 if (rc) {
735 printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n",
736 rc, state, pdn->node->full_name);
737 return;
738 }
739
740 if (state == 0)
741 eeh_clear_slot (pdn->node->parent->child);
742}
743
744/** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
745 * dn -- device node to be reset.
746 */
747
748void
749rtas_set_slot_reset(struct pci_dn *pdn)
750{
751 int i, rc;
752
753 rtas_pci_slot_reset (pdn, 1);
754
755 /* The PCI bus requires that the reset be held high for at least
756 * a 100 milliseconds. We wait a bit longer 'just in case'. */
757
758#define PCI_BUS_RST_HOLD_TIME_MSEC 250
759 msleep (PCI_BUS_RST_HOLD_TIME_MSEC);
760 rtas_pci_slot_reset (pdn, 0);
761
762 /* After a PCI slot has been reset, the PCI Express spec requires
763 * a 1.5 second idle time for the bus to stabilize, before starting
764 * up traffic. */
765#define PCI_BUS_SETTLE_TIME_MSEC 1800
766 msleep (PCI_BUS_SETTLE_TIME_MSEC);
767
768 /* Now double check with the firmware to make sure the device is
769 * ready to be used; if not, wait for recovery. */
770 for (i=0; i<10; i++) {
771 rc = eeh_slot_availability (pdn);
772 if (rc <= 0) break;
773
774 msleep (rc+100);
775 }
776}
777
778/* ------------------------------------------------------------- */
680/* The code below deals with enabling EEH for devices during the 779/* The code below deals with enabling EEH for devices during the
681 * early boot sequence. EEH must be enabled before any PCI probing 780 * early boot sequence. EEH must be enabled before any PCI probing
682 * can be done. 781 * can be done.
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index c47146f74a7b..930a606b4e35 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -52,4 +52,18 @@ extern unsigned long pci_probe_only;
52extern unsigned long pci_assign_all_buses; 52extern unsigned long pci_assign_all_buses;
53extern int pci_read_irq_line(struct pci_dev *pci_dev); 53extern int pci_read_irq_line(struct pci_dev *pci_dev);
54 54
55/* ---- EEH internal-use-only related routines ---- */
56#ifdef CONFIG_EEH
57/**
58 * rtas_set_slot_reset -- unfreeze a frozen slot
59 *
60 * Clear the EEH-frozen condition on a slot. This routine
61 * does this by asserting the PCI #RST line for 1/8th of
62 * a second; this routine will sleep while the adapter is
63 * being reset.
64 */
65void rtas_set_slot_reset (struct pci_dn *);
66
67#endif
68
55#endif /* _ASM_POWERPC_PPC_PCI_H */ 69#endif /* _ASM_POWERPC_PPC_PCI_H */