Commit 26833a5029b710b12f00607fa255ce86909836ad
Committed by
Benjamin Herrenschmidt
1 parent
fd5cee7ce8
powerpc/eeh: Make the delay for PE reset unified
Basically, we have 3 types of resets to fulfil PE reset: fundamental, hot and PHB reset. For the later 2 cases, we need PCI bus reset hold and settlement delay as specified by PCI spec. PowerNV and pSeries platforms are running on top of different firmware and some of the delays have been covered by underly firmware (PowerNV). The patch makes the delays unified to be done in backend, instead of EEH core. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Showing 4 changed files with 30 additions and 15 deletions Side-by-side Diff
arch/powerpc/include/asm/eeh.h
... | ... | @@ -39,6 +39,16 @@ |
39 | 39 | #define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */ |
40 | 40 | |
41 | 41 | /* |
42 | + * Delay for PE reset, all in ms | |
43 | + * | |
44 | + * PCI specification has reset hold time of 100 milliseconds. | |
45 | + * We have 250 milliseconds here. The PCI bus settlement time | |
46 | + * is specified as 1.5 seconds and we have 1.8 seconds. | |
47 | + */ | |
48 | +#define EEH_PE_RST_HOLD_TIME 250 | |
49 | +#define EEH_PE_RST_SETTLE_TIME 1800 | |
50 | + | |
51 | +/* | |
42 | 52 | * The struct is used to trace PE related EEH functionality. |
43 | 53 | * In theory, there will have one instance of the struct to |
44 | 54 | * be created against particular PE. In nature, PEs corelate |
arch/powerpc/kernel/eeh.c
... | ... | @@ -639,20 +639,7 @@ |
639 | 639 | else |
640 | 640 | eeh_ops->reset(pe, EEH_RESET_HOT); |
641 | 641 | |
642 | - /* The PCI bus requires that the reset be held high for at least | |
643 | - * a 100 milliseconds. We wait a bit longer 'just in case'. | |
644 | - */ | |
645 | -#define PCI_BUS_RST_HOLD_TIME_MSEC 250 | |
646 | - msleep(PCI_BUS_RST_HOLD_TIME_MSEC); | |
647 | - | |
648 | 642 | eeh_ops->reset(pe, EEH_RESET_DEACTIVATE); |
649 | - | |
650 | - /* After a PCI slot has been reset, the PCI Express spec requires | |
651 | - * a 1.5 second idle time for the bus to stabilize, before starting | |
652 | - * up traffic. | |
653 | - */ | |
654 | -#define PCI_BUS_SETTLE_TIME_MSEC 1800 | |
655 | - msleep(PCI_BUS_SETTLE_TIME_MSEC); | |
656 | 643 | } |
657 | 644 | |
658 | 645 | /** |
arch/powerpc/platforms/powernv/eeh-ioda.c
... | ... | @@ -417,9 +417,13 @@ |
417 | 417 | |
418 | 418 | /* |
419 | 419 | * Poll state of the PHB until the request is done |
420 | - * successfully. | |
420 | + * successfully. The PHB reset is usually PHB complete | |
421 | + * reset followed by hot reset on root bus. So we also | |
422 | + * need the PCI bus settlement delay. | |
421 | 423 | */ |
422 | 424 | rc = ioda_eeh_phb_poll(phb); |
425 | + if (option == EEH_RESET_DEACTIVATE) | |
426 | + msleep(EEH_PE_RST_SETTLE_TIME); | |
423 | 427 | out: |
424 | 428 | if (rc != OPAL_SUCCESS) |
425 | 429 | return -EIO; |
... | ... | @@ -457,6 +461,8 @@ |
457 | 461 | |
458 | 462 | /* Poll state of the PHB until the request is done */ |
459 | 463 | rc = ioda_eeh_phb_poll(phb); |
464 | + if (option == EEH_RESET_DEACTIVATE) | |
465 | + msleep(EEH_PE_RST_SETTLE_TIME); | |
460 | 466 | out: |
461 | 467 | if (rc != OPAL_SUCCESS) |
462 | 468 | return -EIO; |
463 | 469 | |
... | ... | @@ -480,11 +486,15 @@ |
480 | 486 | eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); |
481 | 487 | ctrl |= PCI_BRIDGE_CTL_BUS_RESET; |
482 | 488 | eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); |
489 | + | |
490 | + msleep(EEH_PE_RST_HOLD_TIME); | |
483 | 491 | break; |
484 | 492 | case EEH_RESET_DEACTIVATE: |
485 | 493 | eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); |
486 | 494 | ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; |
487 | 495 | eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); |
496 | + | |
497 | + msleep(EEH_PE_RST_SETTLE_TIME); | |
488 | 498 | break; |
489 | 499 | } |
490 | 500 |
arch/powerpc/platforms/pseries/eeh_pseries.c
... | ... | @@ -532,10 +532,18 @@ |
532 | 532 | /* If fundamental-reset not supported, try hot-reset */ |
533 | 533 | if (option == EEH_RESET_FUNDAMENTAL && |
534 | 534 | ret == -8) { |
535 | + option = EEH_RESET_HOT; | |
535 | 536 | ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, |
536 | 537 | config_addr, BUID_HI(pe->phb->buid), |
537 | - BUID_LO(pe->phb->buid), EEH_RESET_HOT); | |
538 | + BUID_LO(pe->phb->buid), option); | |
538 | 539 | } |
540 | + | |
541 | + /* We need reset hold or settlement delay */ | |
542 | + if (option == EEH_RESET_FUNDAMENTAL || | |
543 | + option == EEH_RESET_HOT) | |
544 | + msleep(EEH_PE_RST_HOLD_TIME); | |
545 | + else | |
546 | + msleep(EEH_PE_RST_SETTLE_TIME); | |
539 | 547 | |
540 | 548 | return ret; |
541 | 549 | } |