]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/pci/probe.c
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
[karo-tx-linux.git] / drivers / pci / probe.c
index 7fedfeb0871d9bdcf85715121d98ae6ac71e3759..c31310db04047367c44b96ff6afa41a6b991bc28 100644 (file)
@@ -510,16 +510,18 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
        return b;
 }
 
-static void pci_release_host_bridge_dev(struct device *dev)
+static void devm_pci_release_host_bridge_dev(struct device *dev)
 {
        struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
 
        if (bridge->release_fn)
                bridge->release_fn(bridge);
+}
 
-       pci_free_resource_list(&bridge->windows);
-
-       kfree(bridge);
+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));
 }
 
 struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
@@ -531,11 +533,36 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
                return NULL;
 
        INIT_LIST_HEAD(&bridge->windows);
+       bridge->dev.release = pci_release_host_bridge_dev;
 
        return bridge;
 }
 EXPORT_SYMBOL(pci_alloc_host_bridge);
 
+struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
+                                                  size_t priv)
+{
+       struct pci_host_bridge *bridge;
+
+       bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL);
+       if (!bridge)
+               return NULL;
+
+       INIT_LIST_HEAD(&bridge->windows);
+       bridge->dev.release = devm_pci_release_host_bridge_dev;
+
+       return bridge;
+}
+EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
+
+void pci_free_host_bridge(struct pci_host_bridge *bridge)
+{
+       pci_free_resource_list(&bridge->windows);
+
+       kfree(bridge);
+}
+EXPORT_SYMBOL(pci_free_host_bridge);
+
 static const unsigned char pcix_bus_speed[] = {
        PCI_SPEED_UNKNOWN,              /* 0 */
        PCI_SPEED_66MHz_PCIX,           /* 1 */
@@ -719,7 +746,7 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
        dev_set_msi_domain(&bus->dev, d);
 }
 
-int pci_register_host_bridge(struct pci_host_bridge *bridge)
+static int pci_register_host_bridge(struct pci_host_bridge *bridge)
 {
        struct device *parent = bridge->dev.parent;
        struct resource_entry *window, *n;
@@ -834,7 +861,6 @@ free:
        kfree(bus);
        return err;
 }
-EXPORT_SYMBOL(pci_register_host_bridge);
 
 static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
                                           struct pci_dev *bridge, int busnr)
@@ -2333,9 +2359,8 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
 {
 }
 
-static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
-               int bus, struct pci_ops *ops, void *sysdata,
-               struct list_head *resources, struct msi_controller *msi)
+struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
        int error;
        struct pci_host_bridge *bridge;
@@ -2345,13 +2370,11 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
                return NULL;
 
        bridge->dev.parent = parent;
-       bridge->dev.release = pci_release_host_bridge_dev;
 
        list_splice_init(resources, &bridge->windows);
        bridge->sysdata = sysdata;
        bridge->busnr = bus;
        bridge->ops = ops;
-       bridge->msi = msi;
 
        error = pci_register_host_bridge(bridge);
        if (error < 0)
@@ -2363,13 +2386,6 @@ err_out:
        kfree(bridge);
        return NULL;
 }
-
-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
-{
-       return pci_create_root_bus_msi(parent, bus, ops, sysdata, resources,
-                                      NULL);
-}
 EXPORT_SYMBOL_GPL(pci_create_root_bus);
 
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
@@ -2435,24 +2451,28 @@ void pci_bus_release_busn_res(struct pci_bus *b)
                        res, ret ? "can not be" : "is");
 }
 
-struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
-               struct pci_ops *ops, void *sysdata,
-               struct list_head *resources, struct msi_controller *msi)
+int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge)
 {
        struct resource_entry *window;
        bool found = false;
        struct pci_bus *b;
-       int max;
+       int max, bus, ret;
 
-       resource_list_for_each_entry(window, resources)
+       if (!bridge)
+               return -EINVAL;
+
+       resource_list_for_each_entry(window, &bridge->windows)
                if (window->res->flags & IORESOURCE_BUS) {
                        found = true;
                        break;
                }
 
-       b = pci_create_root_bus_msi(parent, bus, ops, sysdata, resources, msi);
-       if (!b)
-               return NULL;
+       ret = pci_register_host_bridge(bridge);
+       if (ret < 0)
+               return ret;
+
+       b = bridge->bus;
+       bus = bridge->busnr;
 
        if (!found) {
                dev_info(&b->dev,
@@ -2466,14 +2486,41 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
        if (!found)
                pci_bus_update_busn_res_end(b, max);
 
-       return b;
+       return 0;
 }
+EXPORT_SYMBOL(pci_scan_root_bus_bridge);
 
 struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
                struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
-       return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources,
-                                    NULL);
+       struct resource_entry *window;
+       bool found = false;
+       struct pci_bus *b;
+       int max;
+
+       resource_list_for_each_entry(window, resources)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found = true;
+                       break;
+               }
+
+       b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
+       if (!b)
+               return NULL;
+
+       if (!found) {
+               dev_info(&b->dev,
+                "No busn resource found for root bus, will use [bus %02x-ff]\n",
+                       bus);
+               pci_bus_insert_busn_res(b, bus, 255);
+       }
+
+       max = pci_scan_child_bus(b);
+
+       if (!found)
+               pci_bus_update_busn_res_end(b, max);
+
+       return b;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);