aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell Currey <ruscur@russell.cc>2016-04-07 02:28:26 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-05-29 23:50:04 -0400
commit871e178e0f2c4fa788f694721a10b4758d494ce1 (patch)
tree145f7bf6050855419da5b9402dbcfa6fdfaea3a3
parent1a695a905c18548062509178b98bc91e67510864 (diff)
powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge
In the "ibm,configure-pe" and "ibm,configure-bridge" RTAS calls, the spec states that values of 9900-9905 can be returned, indicating that software should delay for 10^x (where x is the last digit, i.e. 990x) milliseconds and attempt the call again. Currently, the kernel doesn't know about this, and respecting it fixes some PCI failures when the hypervisor is busy. The delay is capped at 0.2 seconds. Cc: <stable@vger.kernel.org> # 3.10+ Signed-off-by: Russell Currey <ruscur@russell.cc> Acked-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index ac3ffd97e059..405baaf96864 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -615,29 +615,50 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
615{ 615{
616 int config_addr; 616 int config_addr;
617 int ret; 617 int ret;
618 /* Waiting 0.2s maximum before skipping configuration */
619 int max_wait = 200;
618 620
619 /* Figure out the PE address */ 621 /* Figure out the PE address */
620 config_addr = pe->config_addr; 622 config_addr = pe->config_addr;
621 if (pe->addr) 623 if (pe->addr)
622 config_addr = pe->addr; 624 config_addr = pe->addr;
623 625
624 /* Use new configure-pe function, if supported */ 626 while (max_wait > 0) {
625 if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { 627 /* Use new configure-pe function, if supported */
626 ret = rtas_call(ibm_configure_pe, 3, 1, NULL, 628 if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
627 config_addr, BUID_HI(pe->phb->buid), 629 ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
628 BUID_LO(pe->phb->buid)); 630 config_addr, BUID_HI(pe->phb->buid),
629 } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { 631 BUID_LO(pe->phb->buid));
630 ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, 632 } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
631 config_addr, BUID_HI(pe->phb->buid), 633 ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
632 BUID_LO(pe->phb->buid)); 634 config_addr, BUID_HI(pe->phb->buid),
633 } else { 635 BUID_LO(pe->phb->buid));
634 return -EFAULT; 636 } else {
635 } 637 return -EFAULT;
638 }
636 639
637 if (ret) 640 if (!ret)
638 pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", 641 return ret;
639 __func__, pe->phb->global_number, pe->addr, ret); 642
643 /*
644 * If RTAS returns a delay value that's above 100ms, cut it
645 * down to 100ms in case firmware made a mistake. For more
646 * on how these delay values work see rtas_busy_delay_time
647 */
648 if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
649 ret <= RTAS_EXTENDED_DELAY_MAX)
650 ret = RTAS_EXTENDED_DELAY_MIN+2;
651
652 max_wait -= rtas_busy_delay_time(ret);
653
654 if (max_wait < 0)
655 break;
656
657 rtas_busy_delay(ret);
658 }
640 659
660 pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
661 __func__, pe->phb->global_number, pe->addr, ret);
641 return ret; 662 return ret;
642} 663}
643 664