]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/pci/probe.c
PCI: xgene: Remove leftover pci_scan_child_bus() call
[mirror_ubuntu-bionic-kernel.git] / drivers / pci / probe.c
index 14e0ea1ff38b3745111ead4fba31a9fc124c1235..7ec4357d991c0da97be60052e4fd0fb66d74316e 100644 (file)
@@ -516,12 +516,14 @@ static void devm_pci_release_host_bridge_dev(struct device *dev)
 
        if (bridge->release_fn)
                bridge->release_fn(bridge);
+
+       pci_free_resource_list(&bridge->windows);
 }
 
 static void pci_release_host_bridge_dev(struct device *dev)
 {
        devm_pci_release_host_bridge_dev(dev);
-       pci_free_host_bridge(to_pci_host_bridge(dev));
+       kfree(to_pci_host_bridge(dev));
 }
 
 struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
@@ -587,7 +589,7 @@ const unsigned char pcie_link_speed[] = {
        PCIE_SPEED_2_5GT,               /* 1 */
        PCIE_SPEED_5_0GT,               /* 2 */
        PCIE_SPEED_8_0GT,               /* 3 */
-       PCI_SPEED_UNKNOWN,              /* 4 */
+       PCIE_SPEED_16_0GT,              /* 4 */
        PCI_SPEED_UNKNOWN,              /* 5 */
        PCI_SPEED_UNKNOWN,              /* 6 */
        PCI_SPEED_UNKNOWN,              /* 7 */
@@ -1875,6 +1877,38 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
        }
 }
 
+static void pci_configure_ltr(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCIEASPM
+       u32 cap;
+       struct pci_dev *bridge;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
+       if (!(cap & PCI_EXP_DEVCAP2_LTR))
+               return;
+
+       /*
+        * Software must not enable LTR in an Endpoint unless the Root
+        * Complex and all intermediate Switches indicate support for LTR.
+        * PCIe r3.1, sec 6.18.
+        */
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+               dev->ltr_path = 1;
+       else {
+               bridge = pci_upstream_bridge(dev);
+               if (bridge && bridge->ltr_path)
+                       dev->ltr_path = 1;
+       }
+
+       if (dev->ltr_path)
+               pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
+                                        PCI_EXP_DEVCTL2_LTR_EN);
+#endif
+}
+
 static void pci_configure_device(struct pci_dev *dev)
 {
        struct hotplug_params hpp;
@@ -1883,6 +1917,7 @@ static void pci_configure_device(struct pci_dev *dev)
        pci_configure_mps(dev);
        pci_configure_extended_tags(dev, NULL);
        pci_configure_relaxed_ordering(dev);
+       pci_configure_ltr(dev);
 
        memset(&hpp, 0, sizeof(hpp));
        ret = pci_get_hp_params(dev, &hpp);
@@ -2215,22 +2250,27 @@ static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn)
 
 static int only_one_child(struct pci_bus *bus)
 {
-       struct pci_dev *parent = bus->self;
+       struct pci_dev *bridge = bus->self;
 
-       if (!parent || !pci_is_pcie(parent))
+       /*
+        * Systems with unusual topologies set PCI_SCAN_ALL_PCIE_DEVS so
+        * we scan for all possible devices, not just Device 0.
+        */
+       if (pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
                return 0;
-       if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
-               return 1;
 
        /*
-        * PCIe downstream ports are bridges that normally lead to only a
-        * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all
-        * possible devices, not just device 0.  See PCIe spec r3.0,
-        * sec 7.3.1.
+        * A PCIe Downstream Port normally leads to a Link with only Device
+        * 0 on it (PCIe spec r3.1, sec 7.3.1).  As an optimization, scan
+        * only for Device 0 in that situation.
+        *
+        * Checking has_secondary_link is a hack to identify Downstream
+        * Ports because sometimes Switches are configured such that the
+        * PCIe Port Type labels are backwards.
         */
-       if (parent->has_secondary_link &&
-           !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
+       if (bridge && pci_is_pcie(bridge) && bridge->has_secondary_link)
                return 1;
+
        return 0;
 }
 
@@ -2498,7 +2538,14 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
        for_each_pci_bridge(dev, bus) {
                cmax = max;
                max = pci_scan_bridge_extend(bus, dev, max, 0, 0);
-               used_buses += cmax - max;
+
+               /*
+                * Reserve one bus for each bridge now to avoid extending
+                * hotplug bridges too much during the second scan below.
+                */
+               used_buses++;
+               if (cmax - max > 1)
+                       used_buses += cmax - max - 1;
        }
 
        /* Scan bridges that need to be reconfigured */
@@ -2519,12 +2566,14 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
                         * bridges if any.
                         */
                        buses = available_buses / hotplug_bridges;
-                       buses = min(buses, available_buses - used_buses);
+                       buses = min(buses, available_buses - used_buses + 1);
                }
 
                cmax = max;
                max = pci_scan_bridge_extend(bus, dev, cmax, buses, 1);
-               used_buses += max - cmax;
+               /* One bus is already accounted so don't add it again */
+               if (max - cmax > 1)
+                       used_buses += max - cmax - 1;
        }
 
        /*