aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c110
1 files changed, 59 insertions, 51 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/* ------------------------------------------------------- */