Merge tag 'pci-v5.8-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[platform/kernel/linux-starfive.git] / drivers / pci / probe.c
index d9c2c33..2f66988 100644 (file)
@@ -565,7 +565,7 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
        return b;
 }
 
-static void devm_pci_release_host_bridge_dev(struct device *dev)
+static void pci_release_host_bridge_dev(struct device *dev)
 {
        struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
 
@@ -574,12 +574,7 @@ static void devm_pci_release_host_bridge_dev(struct device *dev)
 
        pci_free_resource_list(&bridge->windows);
        pci_free_resource_list(&bridge->dma_ranges);
-}
-
-static void pci_release_host_bridge_dev(struct device *dev)
-{
-       devm_pci_release_host_bridge_dev(dev);
-       kfree(to_pci_host_bridge(dev));
+       kfree(bridge);
 }
 
 static void pci_init_host_bridge(struct pci_host_bridge *bridge)
@@ -599,6 +594,8 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge)
        bridge->native_pme = 1;
        bridge->native_ltr = 1;
        bridge->native_dpc = 1;
+
+       device_initialize(&bridge->dev);
 }
 
 struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
@@ -616,17 +613,25 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
 }
 EXPORT_SYMBOL(pci_alloc_host_bridge);
 
+static void devm_pci_alloc_host_bridge_release(void *data)
+{
+       pci_free_host_bridge(data);
+}
+
 struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
                                                   size_t priv)
 {
+       int ret;
        struct pci_host_bridge *bridge;
 
-       bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL);
+       bridge = pci_alloc_host_bridge(priv);
        if (!bridge)
                return NULL;
 
-       pci_init_host_bridge(bridge);
-       bridge->dev.release = devm_pci_release_host_bridge_dev;
+       ret = devm_add_action_or_reset(dev, devm_pci_alloc_host_bridge_release,
+                                      bridge);
+       if (ret)
+               return NULL;
 
        return bridge;
 }
@@ -634,10 +639,7 @@ EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
 
 void pci_free_host_bridge(struct pci_host_bridge *bridge)
 {
-       pci_free_resource_list(&bridge->windows);
-       pci_free_resource_list(&bridge->dma_ranges);
-
-       kfree(bridge);
+       put_device(&bridge->dev);
 }
 EXPORT_SYMBOL(pci_free_host_bridge);
 
@@ -908,10 +910,11 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
        if (err)
                goto free;
 
-       err = device_register(&bridge->dev);
-       if (err)
+       err = device_add(&bridge->dev);
+       if (err) {
                put_device(&bridge->dev);
-
+               goto free;
+       }
        bus->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(bus->bridge);
        pci_set_bus_of_node(bus);
@@ -977,7 +980,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
 
 unregister:
        put_device(&bridge->dev);
-       device_unregister(&bridge->dev);
+       device_del(&bridge->dev);
 
 free:
        kfree(bus);
@@ -1934,13 +1937,33 @@ static void pci_configure_mps(struct pci_dev *dev)
        struct pci_dev *bridge = pci_upstream_bridge(dev);
        int mps, mpss, p_mps, rc;
 
-       if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
+       if (!pci_is_pcie(dev))
                return;
 
        /* MPS and MRRS fields are of type 'RsvdP' for VFs, short-circuit out */
        if (dev->is_virtfn)
                return;
 
+       /*
+        * For Root Complex Integrated Endpoints, program the maximum
+        * supported value unless limited by the PCIE_BUS_PEER2PEER case.
+        */
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) {
+               if (pcie_bus_config == PCIE_BUS_PEER2PEER)
+                       mps = 128;
+               else
+                       mps = 128 << dev->pcie_mpss;
+               rc = pcie_set_mps(dev, mps);
+               if (rc) {
+                       pci_warn(dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+                                mps);
+               }
+               return;
+       }
+
+       if (!bridge || !pci_is_pcie(bridge))
+               return;
+
        mps = pcie_get_mps(dev);
        p_mps = pcie_get_mps(bridge);
 
@@ -2056,7 +2079,7 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
         * For now, we only deal with Relaxed Ordering issues with Root
         * Ports. Peer-to-Peer DMA is another can of worms.
         */
-       root = pci_find_pcie_root_port(dev);
+       root = pcie_find_root_port(dev);
        if (!root)
                return;
 
@@ -2952,7 +2975,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        return bridge->bus;
 
 err_out:
-       kfree(bridge);
+       put_device(&bridge->dev);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(pci_create_root_bus);