aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-05-19 20:20:49 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-05-19 20:20:49 -0400
commit965b5608f7da181923d766b83ead06cbdc7dd4b3 (patch)
treeb3b6836d4b7192e42c4cf67c2aa7d70f0822bf53 /arch/powerpc/platforms
parentf6869e7fe657bd977e72954cd78c5871a6a4f71d (diff)
Revert "powerpc/powernv: Fundamental reset on PLX ports"
This reverts commit b2b5efcf208ddc9444aca77336627428782a39f4. This code was way too board specific, there are quirks as to how the PERST line is wired on different boards, we'll have to revisit this using/creating appropriate firmware interfaces. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c110
1 files changed, 16 insertions, 94 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 79d0cdf786d0..753f08e36dfa 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -477,127 +477,49 @@ out:
477 return 0; 477 return 0;
478} 478}
479 479
480static bool ioda_eeh_is_plx_dnport(struct pci_dev *dev, int *reg,
481 int *mask, int *len)
482{
483 unsigned short *pid;
484 unsigned short ids[] = {
485 0x10b5, 0x8748, 0x0080, 0x0400, /* PLX#8748 */
486 0x0000, 0x0000, 0x0000, 0x0000, /* End flag */
487 };
488
489 if (!pci_is_pcie(dev))
490 return false;
491 if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
492 return false;
493
494 pid = &ids[0];
495 while (!reg) {
496 if (pid[0] == 0x0)
497 break;
498
499 if (dev->vendor == pid[0] &&
500 dev->device == pid[1]) {
501 *reg = pid[2];
502 *mask = pid[3];
503 *len = 2;
504 return true;
505 }
506 }
507
508 *reg = PCI_BRIDGE_CONTROL;
509 *mask = PCI_BRIDGE_CTL_BUS_RESET;
510 *len = 2;
511 return false;
512}
513
514static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option) 480static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
515 481
516{ 482{
517 struct device_node *dn = pci_device_to_OF_node(dev); 483 struct device_node *dn = pci_device_to_OF_node(dev);
518 struct eeh_dev *edev = of_node_to_eeh_dev(dn); 484 struct eeh_dev *edev = of_node_to_eeh_dev(dn);
519 int aer = edev ? edev->aer_cap : 0; 485 int aer = edev ? edev->aer_cap : 0;
520 int reg, mask, val, len; 486 u32 ctrl;
521 bool is_plx_dnport;
522 487
523 pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n", 488 pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
524 __func__, pci_domain_nr(dev->bus), 489 __func__, pci_domain_nr(dev->bus),
525 dev->bus->number, option); 490 dev->bus->number, option);
526 491
527
528 is_plx_dnport = ioda_eeh_is_plx_dnport(dev, &reg, &mask, &len);
529 if (option == EEH_RESET_FUNDAMENTAL)
530 if (!is_plx_dnport || !edev)
531 option = EEH_RESET_HOT;
532
533 if (option == EEH_RESET_HOT) {
534 reg = PCI_BRIDGE_CONTROL;
535 mask = PCI_BRIDGE_CTL_BUS_RESET;
536 len = 2;
537 }
538
539 if (option == EEH_RESET_DEACTIVATE) {
540 if (!is_plx_dnport || !edev ||
541 !(edev->mode & EEH_DEV_FRESET)) {
542 reg = PCI_BRIDGE_CONTROL;
543 mask = PCI_BRIDGE_CTL_BUS_RESET;
544 len = 2;
545 }
546 }
547
548 switch (option) { 492 switch (option) {
549 case EEH_RESET_FUNDAMENTAL: 493 case EEH_RESET_FUNDAMENTAL:
550 edev->mode |= EEH_DEV_FRESET;
551 /* Fall through */
552 case EEH_RESET_HOT: 494 case EEH_RESET_HOT:
495 /* Don't report linkDown event */
553 if (aer) { 496 if (aer) {
554 /* Mask receiver error */
555 eeh_ops->read_config(dn, aer + PCI_ERR_COR_MASK,
556 4, &val);
557 val |= PCI_ERR_COR_RCVR;
558 eeh_ops->write_config(dn, aer + PCI_ERR_COR_MASK,
559 4, val);
560
561 /* Mask linkDown */
562 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, 497 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
563 4, &val); 498 4, &ctrl);
564 val |= PCI_ERR_UNC_SURPDN; 499 ctrl |= PCI_ERR_UNC_SURPDN;
565 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, 500 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
566 4, val); 501 4, ctrl);
567 } 502 }
568 503
569 eeh_ops->read_config(dn, reg, len, &val); 504 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
570 val |= mask; 505 ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
571 eeh_ops->write_config(dn, reg, len, val); 506 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
572 msleep(EEH_PE_RST_HOLD_TIME); 507 msleep(EEH_PE_RST_HOLD_TIME);
573 508
574 break; 509 break;
575 case EEH_RESET_DEACTIVATE: 510 case EEH_RESET_DEACTIVATE:
576 eeh_ops->read_config(dn, reg, len, &val); 511 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
577 val &= ~mask; 512 ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
578 eeh_ops->write_config(dn, reg, len, val); 513 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
579 msleep(EEH_PE_RST_SETTLE_TIME); 514 msleep(EEH_PE_RST_SETTLE_TIME);
580 515
581 if (edev) 516 /* Continue reporting linkDown event */
582 edev->mode &= ~EEH_DEV_FRESET;
583 if (aer) { 517 if (aer) {
584 /* Clear receive error and enable it */
585 eeh_ops->write_config(dn, aer + PCI_ERR_COR_STATUS,
586 4, PCI_ERR_COR_RCVR);
587 eeh_ops->read_config(dn, aer + PCI_ERR_COR_MASK,
588 4, &val);
589 val &= ~PCI_ERR_COR_RCVR;
590 eeh_ops->write_config(dn, aer + PCI_ERR_COR_MASK,
591 4, val);
592
593 /* Clear linkDown and enable it */
594 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_STATUS,
595 4, PCI_ERR_UNC_SURPDN);
596 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, 518 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
597 4, &val); 519 4, &ctrl);
598 val &= ~PCI_ERR_UNC_SURPDN; 520 ctrl &= ~PCI_ERR_UNC_SURPDN;
599 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, 521 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
600 4, val); 522 4, ctrl);
601 } 523 }
602 524
603 break; 525 break;