diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 110 |
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 */ |
80 | static int ibm_set_eeh_option; | 83 | static int ibm_set_eeh_option; |
81 | static int ibm_set_slot_reset; | 84 | static 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 | */ | ||
187 | int | ||
188 | eeh_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 | */ | ||
469 | static int | ||
470 | eeh_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 | /* ------------------------------------------------------- */ |