aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinas Vepstas <linas@austin.ibm.com>2007-03-19 15:58:07 -0400
committerPaul Mackerras <paulus@samba.org>2007-03-22 07:52:54 -0400
commit9c547768e7d9f456f1b145102e75f79e30f7b709 (patch)
treec55a20e1d621bfefed02a225b7867aeb5fc8d700
parent90375f53960f2b1e8d2a6af3324d440e3a977bf3 (diff)
[POWERPC] EEH: wait for slot status
Modify routine that returns PCI slot status to wait for slot status to become available. This is needed, as slots that are in some remote card cage may go offline for extended periods of time. New users for this routine in following patches. 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.c110
-rw-r--r--include/asm-powerpc/ppc-pci.h3
2 files changed, 61 insertions, 52 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index cb8a151bc9e7..c4604f71c962 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -76,6 +76,9 @@
76 */ 76 */
77#define EEH_MAX_FAILS 2100000 77#define EEH_MAX_FAILS 2100000
78 78
79/* Time to wait for a PCI slot to retport status, in milliseconds */
80#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
81
79/* RTAS tokens */ 82/* RTAS tokens */
80static int ibm_set_eeh_option; 83static int ibm_set_eeh_option;
81static int ibm_set_slot_reset; 84static int ibm_set_slot_reset;
@@ -169,6 +172,55 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
169} 172}
170 173
171/** 174/**
175 * eeh_wait_for_slot_status - returns error status of slot
176 * @pdn pci device node
177 * @max_wait_msecs maximum number to millisecs to wait
178 *
179 * Return negative value if a permanent error, else return
180 * Partition Endpoint (PE) status value.
181 *
182 * If @max_wait_msecs is positive, then this routine will
183 * sleep until a valid status can be obtained, or until
184 * the max allowed wait time is exceeded, in which case
185 * a -2 is returned.
186 */
187int
188eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
189{
190 int rc;
191 int rets[3];
192 int mwait;
193
194 while (1) {
195 rc = read_slot_reset_state(pdn, rets);
196 if (rc) return rc;
197 if (rets[1] == 0) return -1; /* EEH is not supported */
198
199 if (rets[0] != 5) return rets[0]; /* return actual status */
200
201 if (rets[2] == 0) return -1; /* permanently unavailable */
202
203 if (max_wait_msecs <= 0) return -1;
204
205 mwait = rets[2];
206 if (mwait <= 0) {
207 printk (KERN_WARNING
208 "EEH: Firmware returned bad wait value=%d\n", mwait);
209 mwait = 1000;
210 } else if (mwait > 300*1000) {
211 printk (KERN_WARNING
212 "EEH: Firmware is taking too long, time=%d\n", mwait);
213 mwait = 300*1000;
214 }
215 max_wait_msecs -= mwait;
216 msleep (mwait);
217 }
218
219 printk(KERN_WARNING "EEH: Timed out waiting for slot status\n");
220 return -2;
221}
222
223/**
172 * eeh_token_to_phys - convert EEH address token to phys address 224 * eeh_token_to_phys - convert EEH address token to phys address
173 * @token i/o token, should be address in the form 0xA.... 225 * @token i/o token, should be address in the form 0xA....
174 */ 226 */
@@ -459,38 +511,6 @@ EXPORT_SYMBOL(eeh_check_failure);
459/* The code below deals with error recovery */ 511/* The code below deals with error recovery */
460 512
461/** 513/**
462 * eeh_slot_availability - returns error status of slot
463 * @pdn pci device node
464 *
465 * Return negative value if a permanent error, else return
466 * a number of milliseconds to wait until the PCI slot is
467 * ready to be used.
468 */
469static int
470eeh_slot_availability(struct pci_dn *pdn)
471{
472 int rc;
473 int rets[3];
474
475 rc = read_slot_reset_state(pdn, rets);
476
477 if (rc) return rc;
478
479 if (rets[1] == 0) return -1; /* EEH is not supported */
480 if (rets[0] == 0) return 0; /* Oll Korrect */
481 if (rets[0] == 5) {
482 if (rets[2] == 0) return -1; /* permanently unavailable */
483 return rets[2]; /* number of millisecs to wait */
484 }
485 if (rets[0] == 1)
486 return 250;
487
488 printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
489 rc, rets[0], rets[1], rets[2]);
490 return -2;
491}
492
493/**
494 * rtas_pci_enable - enable MMIO or DMA transfers for this slot 514 * rtas_pci_enable - enable MMIO or DMA transfers for this slot
495 * @pdn pci device node 515 * @pdn pci device node
496 */ 516 */
@@ -596,36 +616,24 @@ int rtas_set_slot_reset(struct pci_dn *pdn)
596{ 616{
597 int i, rc; 617 int i, rc;
598 618
599 __rtas_set_slot_reset(pdn); 619 /* Take three shots at resetting the bus */
620 for (i=0; i<3; i++) {
621 __rtas_set_slot_reset(pdn);
600 622
601 /* Now double check with the firmware to make sure the device is 623 rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
602 * ready to be used; if not, wait for recovery. */
603 for (i=0; i<10; i++) {
604 rc = eeh_slot_availability (pdn);
605 if (rc == 0) 624 if (rc == 0)
606 return 0; 625 return 0;
607 626
608 if (rc == -2) {
609 printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n",
610 i, pdn->node->full_name);
611 __rtas_set_slot_reset(pdn);
612 continue;
613 }
614
615 if (rc < 0) { 627 if (rc < 0) {
616 printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", 628 printk (KERN_ERR "EEH: unrecoverable slot failure %s\n",
617 pdn->node->full_name); 629 pdn->node->full_name);
618 return -1; 630 return -1;
619 } 631 }
620 632 printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n",
621 msleep (rc+100); 633 i+1, pdn->node->full_name);
622 } 634 }
623 635
624 rc = eeh_slot_availability (pdn); 636 return -1;
625 if (rc)
626 printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name);
627
628 return rc;
629} 637}
630 638
631/* ------------------------------------------------------- */ 639/* ------------------------------------------------------- */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index f186720d0739..d74b2965bb82 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -70,7 +70,7 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
70void eeh_slot_error_detail (struct pci_dn *pdn, int severity); 70void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
71 71
72/** 72/**
73 * rtas_pci_enableo - enable IO transfers for this slot 73 * rtas_pci_enable - enable IO transfers for this slot
74 * @pdn: pci device node 74 * @pdn: pci device node
75 * @function: either EEH_THAW_MMIO or EEH_THAW_DMA 75 * @function: either EEH_THAW_MMIO or EEH_THAW_DMA
76 * 76 *
@@ -91,6 +91,7 @@ int rtas_pci_enable(struct pci_dn *pdn, int function);
91 * Returns a non-zero value if the reset failed. 91 * Returns a non-zero value if the reset failed.
92 */ 92 */
93int rtas_set_slot_reset (struct pci_dn *); 93int rtas_set_slot_reset (struct pci_dn *);
94int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs);
94 95
95/** 96/**
96 * eeh_restore_bars - Restore device configuration info. 97 * eeh_restore_bars - Restore device configuration info.