]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/platforms/powernv/eeh-ioda.c
powerpc/pci: Mask linkDown on resetting PCI bus
[karo-tx-linux.git] / arch / powerpc / platforms / powernv / eeh-ioda.c
index 268cd46af8f1e57dee7f2f5c69225fa6653f3272..58ef80987eedab40705967ea745b4f628bc667e3 100644 (file)
@@ -474,6 +474,8 @@ 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;
        u32 ctrl;
 
        pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
@@ -483,24 +485,56 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
        switch (option) {
        case EEH_RESET_FUNDAMENTAL:
        case EEH_RESET_HOT:
+               /* Don't report linkDown event */
+               if (aer) {
+                       eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
+                                            4, &ctrl);
+                       ctrl |= PCI_ERR_UNC_SURPDN;
+                        eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
+                                             4, ctrl);
+                }
+
                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, 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);
+
+               /* Continue reporting linkDown event */
+               if (aer) {
+                       eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
+                                            4, &ctrl);
+                       ctrl &= ~PCI_ERR_UNC_SURPDN;
+                       eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
+                                             4, ctrl);
+               }
+
                break;
        }
 
        return 0;
 }
 
+void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
+{
+       struct pci_controller *hose;
+
+       if (pci_is_root_bus(dev->bus)) {
+               hose = pci_bus_to_host(dev->bus);
+               ioda_eeh_root_reset(hose, EEH_RESET_HOT);
+               ioda_eeh_root_reset(hose, EEH_RESET_DEACTIVATE);
+       } else {
+               ioda_eeh_bridge_reset(dev, EEH_RESET_HOT);
+               ioda_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE);
+       }
+}
+
 /**
  * ioda_eeh_reset - Reset the indicated PE
  * @pe: EEH PE