Merge tag 'pci-v4.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[linux] / drivers / pci / probe.c
index 104c46d..e164b5c 100644 (file)
@@ -227,7 +227,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
                }
        } else {
-               res->flags |= (l & IORESOURCE_ROM_ENABLE);
+               if (l & PCI_ROM_ADDRESS_ENABLE)
+                       res->flags |= IORESOURCE_ROM_ENABLE;
                l64 = l & PCI_ROM_ADDRESS_MASK;
                sz64 = sz & PCI_ROM_ADDRESS_MASK;
                mask64 = (u32)PCI_ROM_ADDRESS_MASK;
@@ -521,18 +522,19 @@ static void pci_release_host_bridge_dev(struct device *dev)
        kfree(bridge);
 }
 
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
 {
        struct pci_host_bridge *bridge;
 
-       bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+       bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
        if (!bridge)
                return NULL;
 
        INIT_LIST_HEAD(&bridge->windows);
-       bridge->bus = b;
+
        return bridge;
 }
+EXPORT_SYMBOL(pci_alloc_host_bridge);
 
 static const unsigned char pcix_bus_speed[] = {
        PCI_SPEED_UNKNOWN,              /* 0 */
@@ -717,6 +719,123 @@ 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)
+{
+       struct device *parent = bridge->dev.parent;
+       struct resource_entry *window, *n;
+       struct pci_bus *bus, *b;
+       resource_size_t offset;
+       LIST_HEAD(resources);
+       struct resource *res;
+       char addr[64], *fmt;
+       const char *name;
+       int err;
+
+       bus = pci_alloc_bus(NULL);
+       if (!bus)
+               return -ENOMEM;
+
+       bridge->bus = bus;
+
+       /* temporarily move resources off the list */
+       list_splice_init(&bridge->windows, &resources);
+       bus->sysdata = bridge->sysdata;
+       bus->msi = bridge->msi;
+       bus->ops = bridge->ops;
+       bus->number = bus->busn_res.start = bridge->busnr;
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+       bus->domain_nr = pci_bus_find_domain_nr(bus, parent);
+#endif
+
+       b = pci_find_bus(pci_domain_nr(bus), bridge->busnr);
+       if (b) {
+               /* If we already got to this bus through a different bridge, ignore it */
+               dev_dbg(&b->dev, "bus already known\n");
+               err = -EEXIST;
+               goto free;
+       }
+
+       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(bus),
+                    bridge->busnr);
+
+       err = pcibios_root_bridge_prepare(bridge);
+       if (err)
+               goto free;
+
+       err = device_register(&bridge->dev);
+       if (err)
+               put_device(&bridge->dev);
+
+       bus->bridge = get_device(&bridge->dev);
+       device_enable_async_suspend(bus->bridge);
+       pci_set_bus_of_node(bus);
+       pci_set_bus_msi_domain(bus);
+
+       if (!parent)
+               set_dev_node(bus->bridge, pcibus_to_node(bus));
+
+       bus->dev.class = &pcibus_class;
+       bus->dev.parent = bus->bridge;
+
+       dev_set_name(&bus->dev, "%04x:%02x", pci_domain_nr(bus), bus->number);
+       name = dev_name(&bus->dev);
+
+       err = device_register(&bus->dev);
+       if (err)
+               goto unregister;
+
+       pcibios_add_bus(bus);
+
+       /* Create legacy_io and legacy_mem files for this bus */
+       pci_create_legacy_files(bus);
+
+       if (parent)
+               dev_info(parent, "PCI host bridge to bus %s\n", name);
+       else
+               pr_info("PCI host bridge to bus %s\n", name);
+
+       /* Add initial resources to the bus */
+       resource_list_for_each_entry_safe(window, n, &resources) {
+               list_move_tail(&window->node, &bridge->windows);
+               offset = window->offset;
+               res = window->res;
+
+               if (res->flags & IORESOURCE_BUS)
+                       pci_bus_insert_busn_res(bus, bus->number, res->end);
+               else
+                       pci_bus_add_resource(bus, res, 0);
+
+               if (offset) {
+                       if (resource_type(res) == IORESOURCE_IO)
+                               fmt = " (bus address [%#06llx-%#06llx])";
+                       else
+                               fmt = " (bus address [%#010llx-%#010llx])";
+
+                       snprintf(addr, sizeof(addr), fmt,
+                                (unsigned long long)(res->start - offset),
+                                (unsigned long long)(res->end - offset));
+               } else
+                       addr[0] = '\0';
+
+               dev_info(&bus->dev, "root bus resource %pR%s\n", res, addr);
+       }
+
+       down_write(&pci_bus_sem);
+       list_add_tail(&bus->node, &pci_root_buses);
+       up_write(&pci_bus_sem);
+
+       return 0;
+
+unregister:
+       put_device(&bridge->dev);
+       device_unregister(&bridge->dev);
+
+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)
 {
@@ -1764,8 +1883,7 @@ static void pci_dma_configure(struct pci_dev *dev)
                if (attr == DEV_DMA_NOT_SUPPORTED)
                        dev_warn(&dev->dev, "DMA not supported.\n");
                else
-                       arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
-                                          attr == DEV_DMA_COHERENT);
+                       acpi_dma_configure(&dev->dev, attr);
        }
 
        pci_put_host_bridge_device(bridge);
@@ -2156,113 +2274,43 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
 {
 }
 
-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+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)
 {
        int error;
        struct pci_host_bridge *bridge;
-       struct pci_bus *b, *b2;
-       struct resource_entry *window, *n;
-       struct resource *res;
-       resource_size_t offset;
-       char bus_addr[64];
-       char *fmt;
-
-       b = pci_alloc_bus(NULL);
-       if (!b)
-               return NULL;
 
-       b->sysdata = sysdata;
-       b->ops = ops;
-       b->number = b->busn_res.start = bus;
-#ifdef CONFIG_PCI_DOMAINS_GENERIC
-       b->domain_nr = pci_bus_find_domain_nr(b, parent);
-#endif
-       b2 = pci_find_bus(pci_domain_nr(b), bus);
-       if (b2) {
-               /* If we already got to this bus through a different bridge, ignore it */
-               dev_dbg(&b2->dev, "bus already known\n");
-               goto err_out;
-       }
-
-       bridge = pci_alloc_host_bridge(b);
+       bridge = pci_alloc_host_bridge(0);
        if (!bridge)
-               goto err_out;
+               return NULL;
 
        bridge->dev.parent = parent;
        bridge->dev.release = pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-       error = pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error = device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
-       b->bridge = get_device(&bridge->dev);
-       device_enable_async_suspend(b->bridge);
-       pci_set_bus_of_node(b);
-       pci_set_bus_msi_domain(b);
 
-       if (!parent)
-               set_dev_node(b->bridge, pcibus_to_node(b));
-
-       b->dev.class = &pcibus_class;
-       b->dev.parent = b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
-       error = device_register(&b->dev);
-       if (error)
-               goto class_dev_reg_err;
+       list_splice_init(resources, &bridge->windows);
+       bridge->sysdata = sysdata;
+       bridge->busnr = bus;
+       bridge->ops = ops;
+       bridge->msi = msi;
 
-       pcibios_add_bus(b);
-
-       /* Create legacy_io and legacy_mem files for this bus */
-       pci_create_legacy_files(b);
-
-       if (parent)
-               dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
-       else
-               printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
-
-       /* Add initial resources to the bus */
-       resource_list_for_each_entry_safe(window, n, resources) {
-               list_move_tail(&window->node, &bridge->windows);
-               res = window->res;
-               offset = window->offset;
-               if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
-               else
-                       pci_bus_add_resource(b, res, 0);
-               if (offset) {
-                       if (resource_type(res) == IORESOURCE_IO)
-                               fmt = " (bus address [%#06llx-%#06llx])";
-                       else
-                               fmt = " (bus address [%#010llx-%#010llx])";
-                       snprintf(bus_addr, sizeof(bus_addr), fmt,
-                                (unsigned long long) (res->start - offset),
-                                (unsigned long long) (res->end - offset));
-               } else
-                       bus_addr[0] = '\0';
-               dev_info(&b->dev, "root bus resource %pR%s\n", res, bus_addr);
-       }
+       error = pci_register_host_bridge(bridge);
+       if (error < 0)
+               goto err_out;
 
-       down_write(&pci_bus_sem);
-       list_add_tail(&b->node, &pci_root_buses);
-       up_write(&pci_bus_sem);
+       return bridge->bus;
 
-       return b;
-
-class_dev_reg_err:
-       put_device(&bridge->dev);
-       device_unregister(&bridge->dev);
 err_out:
-       kfree(b);
+       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)
@@ -2343,12 +2391,10 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
                        break;
                }
 
-       b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
+       b = pci_create_root_bus_msi(parent, bus, ops, sysdata, resources, msi);
        if (!b)
                return NULL;
 
-       b->msi = msi;
-
        if (!found) {
                dev_info(&b->dev,
                 "No busn resource found for root bus, will use [bus %02x-ff]\n",