diff options
Diffstat (limited to 'arch/powerpc/platforms/powernv/eeh-ioda.c')
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 110 |
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: return 0; } -static bool ioda_eeh_is_plx_dnport(struct pci_dev *dev, int *reg, - int *mask, int *len) -{ - unsigned short *pid; - unsigned short ids[] = { - 0x10b5, 0x8748, 0x0080, 0x0400, /* PLX#8748 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* End flag */ - }; - - if (!pci_is_pcie(dev)) - return false; - if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) - return false; - - pid = &ids[0]; - while (!reg) { - if (pid[0] == 0x0) - break; - - if (dev->vendor == pid[0] && - dev->device == pid[1]) { - *reg = pid[2]; - *mask = pid[3]; - *len = 2; - return true; - } - } - - *reg = PCI_BRIDGE_CONTROL; - *mask = PCI_BRIDGE_CTL_BUS_RESET; - *len = 2; - return false; -} - static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option) { struct device_node *dn = pci_device_to_OF_node(dev); struct eeh_dev *edev = of_node_to_eeh_dev(dn); int aer = edev ? edev->aer_cap : 0; - int reg, mask, val, len; - bool is_plx_dnport; + u32 ctrl; pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n", __func__, pci_domain_nr(dev->bus), dev->bus->number, option); - - is_plx_dnport = ioda_eeh_is_plx_dnport(dev, ®, &mask, &len); - if (option == EEH_RESET_FUNDAMENTAL) - if (!is_plx_dnport || !edev) - option = EEH_RESET_HOT; - - if (option == EEH_RESET_HOT) { - reg = PCI_BRIDGE_CONTROL; - mask = PCI_BRIDGE_CTL_BUS_RESET; - len = 2; - } - - if (option == EEH_RESET_DEACTIVATE) { - if (!is_plx_dnport || !edev || - !(edev->mode & EEH_DEV_FRESET)) { - reg = PCI_BRIDGE_CONTROL; - mask = PCI_BRIDGE_CTL_BUS_RESET; - len = 2; - } - } - switch (option) { case EEH_RESET_FUNDAMENTAL: - edev->mode |= EEH_DEV_FRESET; - /* Fall through */ case EEH_RESET_HOT: + /* Don't report linkDown event */ if (aer) { - /* Mask receiver error */ - eeh_ops->read_config(dn, aer + PCI_ERR_COR_MASK, - 4, &val); - val |= PCI_ERR_COR_RCVR; - eeh_ops->write_config(dn, aer + PCI_ERR_COR_MASK, - 4, val); - - /* Mask linkDown */ eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, - 4, &val); - val |= PCI_ERR_UNC_SURPDN; + 4, &ctrl); + ctrl |= PCI_ERR_UNC_SURPDN; eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, - 4, val); - } + 4, ctrl); + } - eeh_ops->read_config(dn, reg, len, &val); - val |= mask; - eeh_ops->write_config(dn, reg, len, val); + eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); + ctrl |= PCI_BRIDGE_CTL_BUS_RESET; + eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); msleep(EEH_PE_RST_HOLD_TIME); break; case EEH_RESET_DEACTIVATE: - eeh_ops->read_config(dn, reg, len, &val); - val &= ~mask; - eeh_ops->write_config(dn, reg, len, val); + eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; + eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); msleep(EEH_PE_RST_SETTLE_TIME); - if (edev) - edev->mode &= ~EEH_DEV_FRESET; + /* Continue reporting linkDown event */ if (aer) { - /* Clear receive error and enable it */ - eeh_ops->write_config(dn, aer + PCI_ERR_COR_STATUS, - 4, PCI_ERR_COR_RCVR); - eeh_ops->read_config(dn, aer + PCI_ERR_COR_MASK, - 4, &val); - val &= ~PCI_ERR_COR_RCVR; - eeh_ops->write_config(dn, aer + PCI_ERR_COR_MASK, - 4, val); - - /* Clear linkDown and enable it */ - eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_STATUS, - 4, PCI_ERR_UNC_SURPDN); eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, - 4, &val); - val &= ~PCI_ERR_UNC_SURPDN; + 4, &ctrl); + ctrl &= ~PCI_ERR_UNC_SURPDN; eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, - 4, val); + 4, ctrl); } break; |