diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2020-12-19 18:01:52 +0100 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2021-03-20 17:02:16 +0100 |
| commit | 3b0acc0ac3c7dc0ecb99215c7eb87a41a4acd79f (patch) | |
| tree | 2300b1abc93141aaf52bb639249c2a0d0261f42e | |
| parent | 1c9bc5ddbff8a4399597ecba68dc47ec2fb41679 (diff) | |
| download | playground-3b0acc0ac3c7dc0ecb99215c7eb87a41a4acd79f.tar.gz | |
powerpc: rework PCI host allocation
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
37 files changed, 202 insertions, 168 deletions
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index d2a2a14e56f91..e18d1858bcbbd 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -50,14 +50,13 @@ struct pci_controller_ops { * Structure of a PCI controller (host bridge) */ struct pci_controller { - struct pci_bus *bus; + struct pci_host_bridge *bridge; char is_dynamic; #ifdef CONFIG_PPC64 int node; #endif struct device_node *dn; struct list_head list_node; - struct device *parent; int first_busno; int last_busno; @@ -79,7 +78,6 @@ struct pci_controller { resource_size_t isa_mem_size; struct pci_controller_ops controller_ops; - struct pci_ops *ops; unsigned int __iomem *cfg_addr; void __iomem *cfg_data; @@ -282,6 +280,7 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, /* Allocate & free a PCI host bridge structure */ extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); +extern struct pci_controller *pcibios_alloc_controller_early(struct device_node *dev); extern void pcibios_free_controller(struct pci_controller *phb); extern void pcibios_free_controller_deferred(struct pci_host_bridge *bridge); diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 6436f0b41539e..85775a84259c5 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -115,7 +115,7 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, extern resource_size_t pcibios_io_space_offset(struct pci_controller *hose); extern void pcibios_setup_bus_self(struct pci_bus *bus); extern void pcibios_setup_phb_io_space(struct pci_controller *hose); -extern void pcibios_scan_phb(struct pci_controller *hose); +extern void pcibios_scan_host_bridge(struct pci_host_bridge *hose); #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 845e024321d47..b3d11bca47f24 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -849,9 +849,10 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) { struct eeh_dev *edev; struct pci_dev *pdev; + struct pci_host_bridge *bridge = pe->phb->bridge; if (pe->type & EEH_PE_PHB) - return pe->phb->bus; + return bridge->bus; /* The primary bus might be cached during probe time */ if (pe->state & EEH_PE_PRI_BUS) diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index f89376ff633e7..55b2cd2b020a8 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -35,6 +35,7 @@ static int of_pci_phb_probe(struct platform_device *dev) { struct pci_controller *phb; + struct pci_host_bridge *bridge; /* Check if we can do that ... */ if (ppc_md.pci_setup_phb == NULL) @@ -47,8 +48,9 @@ static int of_pci_phb_probe(struct platform_device *dev) if (!phb) return -ENODEV; + bridge = phb->bridge; /* Setup parent in sysfs */ - phb->parent = &dev->dev; + bridge->dev.parent = &dev->dev; /* Setup the PHB using arch provided callback */ if (ppc_md.pci_setup_phb(phb)) { @@ -66,18 +68,18 @@ static int of_pci_phb_probe(struct platform_device *dev) eeh_phb_pe_create(phb); /* Scan the bus */ - pcibios_scan_phb(phb); - if (phb->bus == NULL) + pcibios_scan_host_bridge(bridge); + if (bridge->bus == NULL) return -ENXIO; /* Claim resources. This might need some rework as well depending * whether we are doing probe-only or not, like assigning unassigned * resources etc... */ - pcibios_claim_one_bus(phb->bus); + pcibios_claim_one_bus(bridge->bus); /* Add probed PCI devices to the device model */ - pci_bus_add_devices(phb->bus); + pci_bus_add_devices(bridge->bus); return 0; } diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index d416607d3e5c5..2a75d056d693f 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -20,6 +20,7 @@ #include <linux/export.h> #include <linux/of_address.h> #include <linux/of_pci.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/shmem_fs.h> #include <linux/list.h> @@ -105,19 +106,41 @@ static int get_phb_number(struct device_node *dn) return phb_id; } -struct pci_controller *pcibios_alloc_controller(struct device_node *dev) +static void pcibios_unlink_controller(struct pci_host_bridge *bridge) { - struct pci_controller *phb; + struct pci_controller *phb = pci_host_bridge_priv(bridge); - phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL); - if (phb == NULL) - return NULL; + spin_lock(&hose_spinlock); + + /* Clear bit of phb_bitmap to allow reuse of this PHB number. */ + if (phb->global_number < MAX_PHBS) + clear_bit(phb->global_number, phb_bitmap); + + list_del(&phb->list_node); + spin_unlock(&hose_spinlock); +} + +static void pcibios_release_early_host_bridge(struct device *dev) +{ + struct pci_host_bridge *bridge = to_pci_host_bridge(dev); + + pcibios_unlink_controller(bridge); + + pci_free_resource_list(&bridge->windows); + pci_free_resource_list(&bridge->dma_ranges); + WARN(1, "attempt to free non-dynamic PHB\n"); +} + +static void pcibios_init_bridge(struct pci_host_bridge *bridge, struct device_node *dev) +{ + struct pci_controller *phb = pci_host_bridge_priv(bridge); + + phb->bridge = bridge; spin_lock(&hose_spinlock); phb->global_number = get_phb_number(dev); list_add_tail(&phb->list_node, &hose_list); spin_unlock(&hose_spinlock); phb->dn = dev; - phb->is_dynamic = slab_is_available(); #ifdef CONFIG_PPC64 if (dev) { int nid = of_node_to_nid(dev); @@ -128,23 +151,45 @@ struct pci_controller *pcibios_alloc_controller(struct device_node *dev) PHB_SET_NODE(phb, nid); } #endif - return phb; +} + +struct pci_controller *pcibios_alloc_controller(struct device_node *dev) +{ + struct pci_host_bridge *bridge; + + bridge = pci_alloc_host_bridge(sizeof(struct pci_controller)); + if (!bridge) + return NULL; + + pcibios_init_bridge(bridge, dev); + + pci_set_host_bridge_release(bridge, pcibios_unlink_controller, NULL); + + return pci_host_bridge_priv(bridge); } EXPORT_SYMBOL_GPL(pcibios_alloc_controller); -void pcibios_free_controller(struct pci_controller *phb) +struct pci_controller * __init +pcibios_alloc_controller_early(struct device_node *dev) { - spin_lock(&hose_spinlock); + struct pci_host_bridge *bridge; - /* Clear bit of phb_bitmap to allow reuse of this PHB number. */ - if (phb->global_number < MAX_PHBS) - clear_bit(phb->global_number, phb_bitmap); + bridge = memblock_alloc(sizeof(struct pci_host_bridge) + + sizeof(struct pci_controller), SMP_CACHE_BYTES); + if (!bridge) + panic("%s: Failed to allocate pci_host_bridge\n", __func__); - list_del(&phb->list_node); - spin_unlock(&hose_spinlock); + pci_init_host_bridge(bridge); + pcibios_init_bridge(bridge, dev); + + bridge->dev.release = pcibios_release_early_host_bridge; - if (phb->is_dynamic) - kfree(phb); + return pci_host_bridge_priv(bridge); +} + +void pcibios_free_controller(struct pci_controller *phb) +{ + pci_free_host_bridge(phb->bridge); } EXPORT_SYMBOL_GPL(pcibios_free_controller); @@ -1502,8 +1547,7 @@ resource_size_t pcibios_io_space_offset(struct pci_controller *hose) return (unsigned long) hose->io_base_virt - _IO_BASE; } -static void pcibios_setup_phb_resources(struct pci_controller *hose, - struct list_head *resources) +static void pcibios_setup_phb_resources(struct pci_controller *hose) { struct resource *res; resource_size_t offset; @@ -1521,7 +1565,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, pr_debug("PCI: PHB IO resource = %pR off 0x%08llx\n", res, (unsigned long long)offset); - pci_add_resource_offset(resources, res, offset); + pci_add_resource_offset(&hose->bridge->windows, res, offset); } /* Hookup PHB Memory resources */ @@ -1534,7 +1578,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, pr_debug("PCI: PHB MEM resource %d = %pR off 0x%08llx\n", i, res, (unsigned long long)offset); - pci_add_resource_offset(resources, res, offset); + pci_add_resource_offset(&hose->bridge->windows, res, offset); } } @@ -1583,7 +1627,7 @@ fake_pci_bus(struct pci_controller *hose, int busnr) } bus.number = busnr; bus.sysdata = hose; - bus.ops = hose? hose->ops: &null_pci_ops; + bus.ops = hose? hose->bridge->ops: &null_pci_ops; return &bus; } @@ -1616,62 +1660,52 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) } /** - * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus - * @hose: Pointer to the PCI host controller instance structure + * pci_scan_host_bridge - Given a pci_controller, setup and scan the PCI bus + * @bridge: Pointer to the PCI host controller instance structure */ -void pcibios_scan_phb(struct pci_controller *hose) +void pci_scan_host_bridge(struct pci_host_bridge *bridge) { + struct pci_controller *hose = pci_host_bridge_priv(bridge); struct device_node *node = hose->dn; - struct pci_host_bridge *bridge; int mode; int error; - /* TODO: merge pci_controller into pci_host_bridge */ - bridge = pci_alloc_host_bridge(0); - if (!bridge) - return; - pr_debug("PCI: Scanning PHB %pOF\n", node); /* Get some IO space for the new PHB */ pcibios_setup_phb_io_space(hose); /* Wire up PHB bus resources */ - pcibios_setup_phb_resources(hose, &bridge->windows); + pcibios_setup_phb_resources(hose); - bridge->dev.parent = hose->parent; bridge->sysdata = hose; bridge->busnr = hose->first_busno; - bridge->ops = hose->ops; + bridge->custom_bus_scan = 1; hose->busn.start = hose->first_busno; hose->busn.end = hose->last_busno; hose->busn.flags = IORESOURCE_BUS; pci_add_resource(&bridge->windows, &hose->busn); + mode = PCI_PROBE_NORMAL; + if (node && hose->controller_ops.probe_mode) + mode = hose->controller_ops.probe_mode(bridge->bus); + /* Get probe mode and perform scan */ + pr_debug(" probe mode: %d\n", mode); + if (mode == PCI_PROBE_DEVTREE) + bridge->custom_bus_scan = 1; + /* Create an empty bus for the toplevel */ - error = pci_register_host_bridge(bridge); + error = pci_scan_root_bus_bridge(bridge); if (error) { pr_err("Failed to create bus for PCI domain %04x: %d\n", hose->global_number, error); pci_free_host_bridge(bridge); return; } - hose->bus = bridge->bus; - /* Get probe mode and perform scan */ - mode = PCI_PROBE_NORMAL; - if (node && hose->controller_ops.probe_mode) - mode = hose->controller_ops.probe_mode(bus); - pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) - of_scan_bus(node, bus); - - if (mode == PCI_PROBE_NORMAL) { - pci_bus_update_busn_res_end(bus, 255); - hose->last_busno = pci_scan_child_bus(bus); - pci_bus_update_busn_res_end(bus, hose->last_busno); - } + of_scan_bus(node, bridge->bus); /* Platform gets a chance to do some global fixups before * we proceed to resource allocation @@ -1680,13 +1714,13 @@ void pcibios_scan_phb(struct pci_controller *hose) ppc_md.pcibios_fixup_phb(hose); /* Configure PCI Express settings */ - if (bus && !pci_has_flag(PCI_PROBE_ONLY)) { + if (bridge->bus && !pci_has_flag(PCI_PROBE_ONLY)) { struct pci_bus *child; - list_for_each_entry(child, &bus->children, node) + list_for_each_entry(child, &bridge->bus->children, node) pcie_bus_configure_settings(child); } } -EXPORT_SYMBOL_GPL(pcibios_scan_phb); +EXPORT_SYMBOL_GPL(pcibios_scan_host_bridge); static void fixup_hide_host_resource_fsl(struct pci_dev *dev) { diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 2fc12198ec071..1d7d7d2deeed5 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -39,10 +39,10 @@ struct pci_bus *pci_find_bus_by_node(struct device_node *dn) { struct pci_dn *pdn = PCI_DN(dn); - if (!pdn || !pdn->phb || !pdn->phb->bus) + if (!pdn || !pdn->phb || !pdn->phb->bridge || !pdn->phb->bridge->bus) return NULL; - return find_bus_among_children(pdn->phb->bus, dn); + return find_bus_among_children(pdn->phb->bridge->bus, dn); } EXPORT_SYMBOL_GPL(pci_find_bus_by_node); diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index b49e1060a3bff..634dae42fff53 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -234,6 +234,7 @@ void pcibios_setup_phb_io_space(struct pci_controller *hose) static int __init pcibios_init(void) { struct pci_controller *hose, *tmp; + struct pci_host_bridge *bridge; int next_busno = 0; printk(KERN_INFO "PCI: Probing PCI hardware\n"); @@ -243,11 +244,12 @@ static int __init pcibios_init(void) /* Scan all of the recorded PCI controllers. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + bridge = hose->bridge; if (pci_assign_all_buses) hose->first_busno = next_busno; hose->last_busno = 0xff; - pcibios_scan_phb(hose); - pci_bus_add_devices(hose->bus); + pcibios_scan_host_bridge(bridge); + pci_bus_add_devices(bridge->bus); if (pci_assign_all_buses || next_busno <= hose->last_busno) next_busno = hose->last_busno + pcibios_assign_bus_offset; } diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9312e6eda7ff2..bcf5e1d0b1e61 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -55,14 +55,14 @@ static int __init pcibios_init(void) /* Scan all of the recorded PCI controllers. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) - pcibios_scan_phb(hose); + pcibios_scan_host_bridge(hose->bridge); /* Call common code to handle resource allocation */ pcibios_resource_survey(); /* Add devices. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) - pci_bus_add_devices(hose->bus); + pci_bus_add_devices(hose->bridge->bus); /* Call machine dependent fixup */ if (ppc_md.pcibios_fixup) diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 781c1869902ef..0e501320b5558 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -234,7 +234,7 @@ int rtas_setup_phb(struct pci_controller *phb) if (phb_set_bus_ranges(dev, phb)) return 1; - phb->ops = &rtas_pci_ops; + phb->bridge->ops = &rtas_pci_ops; phb->buid = get_phb_buid(dev); return 0; diff --git a/arch/powerpc/platforms/4xx/pci.c b/arch/powerpc/platforms/4xx/pci.c index c13d64c3b0194..1b29b178176ab 100644 --- a/arch/powerpc/platforms/4xx/pci.c +++ b/arch/powerpc/platforms/4xx/pci.c @@ -1983,7 +1983,7 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) hose->cfg_addr, hose->cfg_data); /* Setup config space */ - hose->ops = &ppc4xx_pciex_pci_ops; + hose->bridge->ops = &ppc4xx_pciex_pci_ops; port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 3b7d70d716925..e2ec0f05888a2 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -110,7 +110,7 @@ static void __init efika_pcisetup(void) printk(" controlled by %pOF\n", pcictrl); printk("\n"); - hose = pcibios_alloc_controller(pcictrl); + hose = pcibios_alloc_controller_early(pcictrl); if (!hose) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't allocate PCI controller structure for %pOF\n", @@ -120,7 +120,7 @@ static void __init efika_pcisetup(void) hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; - hose->ops = &rtas_pci_ops; + hose->bridge->ops = &rtas_pci_ops; pci_process_bridge_OF_ranges(hose, pcictrl, 0); return; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index af0f799952147..d5d19e68e4fe5 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -393,14 +393,14 @@ mpc52xx_add_bridge(struct device_node *node) * tree are needed to configure the 52xx PCI controller. Rather * than parse the tree here, let pci_process_bridge_OF_ranges() * do it for us and extract the values after the fact */ - hose = pcibios_alloc_controller(node); + hose = pcibios_alloc_controller_early(node); if (!hose) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - hose->ops = &mpc52xx_pci_ops; + hose->bridge->ops = &mpc52xx_pci_ops; pci_regs = ioremap(rsrc.start, resource_size(&rsrc)); if (!pci_regs) diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c index 3b5cb39a564c8..c500eef430ecb 100644 --- a/arch/powerpc/platforms/82xx/pq2.c +++ b/arch/powerpc/platforms/82xx/pq2.c @@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(struct device_node *np) pci_add_flags(PCI_REASSIGN_ALL_BUS); - hose = pcibios_alloc_controller(np); + hose = pcibios_alloc_controller_early(np); if (!hose) return; diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 9d252c554f7f8..a4059f2ca4c38 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c @@ -48,7 +48,7 @@ static int __init amigaone_add_bridge(struct device_node *dev) printk(KERN_WARNING "Can't get bus-range for %pOF, assume" " bus 0\n", dev); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (hose == NULL) return -ENOMEM; diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c index 93ea41680f544..70b1e237d94e2 100644 --- a/arch/powerpc/platforms/cell/spider-pci.c +++ b/arch/powerpc/platforms/cell/spider-pci.c @@ -66,7 +66,7 @@ static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src, spiderpci_io_flush(iowa_mem_find_bus(src)); } -static int __init spiderpci_pci_setup_chip(struct pci_controller *phb, +static int __init spiderpci_pci_setup_chip(struct pci_host_bridge *bridge, void __iomem *regs) { void *dummy_page_va; @@ -96,9 +96,9 @@ static int __init spiderpci_pci_setup_chip(struct pci_controller *phb, return -1; } - dummy_page_da = dma_map_single(phb->parent, dummy_page_va, + dummy_page_da = dma_map_single(bridge->dev.parent, dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(phb->parent, dummy_page_da)) { + if (dma_mapping_error(bridge->dev.parent, dummy_page_da)) { pr_err("SPIDER-IOWA:Map dummy page filed.\n"); kfree(dummy_page_va); return -1; @@ -140,7 +140,7 @@ int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data) priv->regs = regs; bus->private = priv; - if (spiderpci_pci_setup_chip(bus->phb, regs)) + if (spiderpci_pci_setup_chip(bus->phb->bridge, regs)) goto error; return 0; diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 8c421dc78b283..4fc949526741f 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -194,7 +194,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d rtas = of_find_node_by_name (root, "rtas"); if (rtas) { - hose->ops = &rtas_pci_ops; + hose->bridge->ops = &rtas_pci_ops; of_node_put(rtas); } else { printk ("RTAS supporting Pegasos OF not found, please upgrade" @@ -256,7 +256,7 @@ chrp_find_bridges(void) printk(" at %llx", (unsigned long long)r.start); printk("\n"); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (!hose) { printk("Can't allocate PCI controller structure for %pOF\n", dev); @@ -275,7 +275,7 @@ chrp_find_bridges(void) setup_grackle(hose); } else if (is_longtrail) { void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); - hose->ops = &gg2_pci_ops; + hose->bridge->ops = &gg2_pci_ops; hose->cfg_data = p; gg2_pci_config_base = p; } else if (is_pegasos == 1) { @@ -300,7 +300,7 @@ chrp_find_bridges(void) } else { printk("No methods for %pOF (model %s), using RTAS\n", dev, model); - hose->ops = &rtas_pci_ops; + hose->bridge->ops = &rtas_pci_ops; } pci_process_bridge_OF_ranges(hose, dev, index == 0); diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index eb8342e7f84e9..bb45f07cead54 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -48,7 +48,7 @@ static int __init linkstation_add_bridge(struct device_node *dev) printk(KERN_WARNING "Can't get bus-range for %pOF, assume" " bus 0\n", dev); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (hose == NULL) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c index c06a0490d157f..a293e4b403c92 100644 --- a/arch/powerpc/platforms/embedded6xx/mvme5100.c +++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c @@ -114,7 +114,7 @@ static int __init mvme5100_add_bridge(struct device_node *dev) bus_range = of_get_property(dev, "bus-range", &len); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (hose == NULL) return -ENOMEM; diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index e188b90f7016e..52a084f4a8289 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c @@ -46,7 +46,7 @@ static int __init storcenter_add_bridge(struct device_node *dev) printk("Adding PCI host bridge %pOF\n", dev); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (hose == NULL) return -ENOMEM; diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index a20b9576de225..05246db597b5d 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -450,7 +450,7 @@ static void __init setup_u3_agp(struct pci_controller* hose) */ hose->first_busno = 0xf0; hose->last_busno = 0xff; - hose->ops = &u3_agp_pci_ops; + hose->bridge->ops = &u3_agp_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); @@ -462,7 +462,7 @@ static void __init setup_u4_pcie(struct pci_controller* hose) /* We currently only implement the "non-atomic" config space, to * be optimised later. */ - hose->ops = &u4_pcie_pci_ops; + hose->bridge->ops = &u4_pcie_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); @@ -471,7 +471,7 @@ static void __init setup_u4_pcie(struct pci_controller* hose) static void __init setup_u3_ht(struct pci_controller* hose) { - hose->ops = &u3_ht_pci_ops; + hose->bridge->ops = &u3_ht_pci_ops; /* We hard code the address because of the different size of * the reg address cell, we shall fix that by killing struct @@ -502,7 +502,7 @@ static int __init maple_add_bridge(struct device_node *dev) dev); } - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (hose == NULL) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 8779b107d8727..deeeec745ef41 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -233,7 +233,7 @@ static struct pci_ops pa_pxp_ops = { static void __init setup_pa_pxp(struct pci_controller *hose) { - hose->ops = &pa_pxp_ops; + hose->bridge->ops = &pa_pxp_ops; hose->cfg_data = ioremap(0xe0000000, 0x10000000); } @@ -243,7 +243,7 @@ static int __init pas_add_bridge(struct device_node *dev) pr_debug("Adding PCI host bridge %pOF\n", dev); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (!hose) return -ENOMEM; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index e9abe0f2e7f0a..c231b09c5fc96 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -204,7 +204,7 @@ static void __init setup_chaos(struct pci_controller *hose, struct resource *addr) { /* assume a `chaos' bridge */ - hose->ops = &chaos_pci_ops; + hose->bridge->ops = &chaos_pci_ops; hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000); } @@ -601,7 +601,7 @@ static void __init fixup_nec_usb2(void) static void __init setup_bandit(struct pci_controller *hose, struct resource *addr) { - hose->ops = ¯isc_pci_ops; + hose->bridge->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000); init_bandit(hose); @@ -612,7 +612,7 @@ static int __init setup_uninorth(struct pci_controller *hose, { pci_add_flags(PCI_REASSIGN_ALL_BUS); has_uninorth = 1; - hose->ops = ¯isc_pci_ops; + hose->bridge->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000); /* We "know" that the bridge at f2000000 has the PCI slots. */ @@ -635,7 +635,7 @@ static void __init setup_u3_agp(struct pci_controller* hose) hose->first_busno = 0xf0; hose->last_busno = 0xff; has_uninorth = 1; - hose->ops = ¯isc_pci_ops; + hose->bridge->ops = ¯isc_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); u3_agp = hose; @@ -646,7 +646,7 @@ static void __init setup_u4_pcie(struct pci_controller* hose) /* We currently only implement the "non-atomic" config space, to * be optimised later. */ - hose->ops = &u4_pcie_pci_ops; + hose->bridge->ops = &u4_pcie_pci_ops; hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); @@ -704,7 +704,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) struct resource cfg_res, self_res; u32 decode; - hose->ops = &u3_ht_pci_ops; + hose->bridge->ops = &u3_ht_pci_ops; /* Get base addresses from OF tree */ @@ -789,7 +789,7 @@ static int __init pmac_add_bridge(struct device_node *dev) " bus 0\n", dev); } - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (!hose) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index b711dc3262a30..b5dd4f3a0dd15 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -23,9 +23,10 @@ static struct pci_dev *get_pci_dev(struct device_node *dn) { struct pci_dn *pdn = PCI_DN(dn); + struct pci_host_bridge *bridge = pdn->phb->bridge; struct pci_dev *pdev; - pdev = pci_get_domain_bus_and_slot(pci_domain_nr(pdn->phb->bus), + pdev = pci_get_domain_bus_and_slot(pci_domain_nr(bridge->bus), pdn->busno, pdn->devfn); /* @@ -502,6 +503,7 @@ static struct iommu_table_group *pnv_npu_compound_attach(struct pnv_ioda_pe *pe) struct pci_dev *gpdev = NULL; struct pci_dev *npdev; struct pnv_ioda_pe *gpe = get_gpu_pci_dev_and_pe(pe, &gpdev); + struct pci_host_bridge *bridge = pe->phb->hose->bridge; WARN_ON(!(pe->flags & PNV_IODA_PE_DEV)); if (!gpe) @@ -527,7 +529,7 @@ static struct iommu_table_group *pnv_npu_compound_attach(struct pnv_ioda_pe *pe) npucomp = container_of(table_group, struct npu_comp, table_group); pnv_comp_attach_table_group(npucomp, pe); - list_for_each_entry(npdev, &pe->phb->hose->bus->devices, bus_list) { + list_for_each_entry(npdev, &bridge->bus->devices, bus_list) { struct pci_dev *gpdevtmp = pnv_pci_get_gpu_dev(npdev); if (gpdevtmp != gpdev) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index f0f901683a2fe..edd8c5a810ebd 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1186,7 +1186,7 @@ static void pnv_pci_ioda_setup_nvlink(void) if (phb->type == PNV_PHB_NPU_NVLINK) { /* PE#0 is needed for error reporting */ pnv_ioda_reserve_pe(phb, 0); - pnv_ioda_setup_npu_PEs(hose->bus); + pnv_ioda_setup_npu_PEs(hose->bridge->bus); if (phb->model == PNV_PHB_MODEL_NPU2) WARN_ON_ONCE(pnv_npu2_init(hose)); } @@ -1658,6 +1658,7 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) { + struct pci_host_bridge *bridge = phb->hose->bridge; struct page *tce_mem = NULL; struct iommu_table *tbl; unsigned int weight, total_weight = 0; @@ -1672,7 +1673,7 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb, if (!weight) return; - pci_walk_bus(phb->hose->bus, pnv_pci_ioda_dev_dma_weight, + pci_walk_bus(bridge->bus, pnv_pci_ioda_dev_dma_weight, &total_weight); segs = (weight * phb->ioda.dma32_count) / total_weight; if (!segs) @@ -2445,7 +2446,7 @@ static void pnv_pci_enable_bridges(void) struct pci_controller *hose; list_for_each_entry(hose, &hose_list, list_node) - pnv_pci_enable_bridge(hose->bus); + pnv_pci_enable_bridge(hose->bridge->bus); } static void pnv_pci_ioda_fixup(void) @@ -2927,7 +2928,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, sizeof(*phb)); /* Allocate PCI controller */ - phb->hose = hose = pcibios_alloc_controller(np); + phb->hose = hose = pcibios_alloc_controller_early(np); if (!phb->hose) { pr_err(" Can't allocate PCI controller for %pOF\n", np); @@ -3099,7 +3100,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb->ioda.io_size, phb->ioda.io_segsize); - phb->hose->ops = &pnv_pci_ops; + phb->hose->bridge->ops = &pnv_pci_ops; phb->get_pe_state = pnv_ioda_get_pe_state; phb->freeze_pe = pnv_ioda_freeze_pe; phb->unfreeze_pe = pnv_ioda_unfreeze_pe; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 9fc5217f0c8e5..983b6f5cb3138 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -495,6 +495,7 @@ static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) { + struct pci_host_bridge *bridge = phb->bridge; struct device_node *node; const unsigned long *basep; const u32 *sizep; @@ -514,7 +515,7 @@ static void iommu_table_setparms(struct pci_controller *phb, if (!is_kdump_kernel()) memset((void *)tbl->it_base, 0, *sizep); - tbl->it_busno = phb->bus->number; + tbl->it_busno = bridge->bus->number; tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K; /* Units of tce entries */ @@ -547,11 +548,12 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, struct iommu_table_group *table_group, const __be32 *dma_window) { + struct pci_host_bridge *bridge = phb->bridge; unsigned long offset, size; of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); - tbl->it_busno = phb->bus->number; + tbl->it_busno = bridge->bus->number; tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K; tbl->it_base = 0; tbl->it_blocksize = 16; @@ -1335,6 +1337,7 @@ out_unlock: static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) { + struct pci_host_bridge *bridge; struct device_node *pdn, *dn; struct iommu_table *tbl; const __be32 *dma_window = NULL; @@ -1367,6 +1370,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) pr_debug(" parent is %pOF\n", pdn); pci = PCI_DN(pdn); + bridge = pci->phb->bridge; if (!pci->table_group) { pci->table_group = iommu_pseries_alloc_group(pci->phb->node); tbl = pci->table_group->tables[0]; @@ -1375,7 +1379,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) tbl->it_ops = &iommu_table_lpar_multi_ops; iommu_init_table(tbl, pci->phb->node, 0, 0); iommu_register_group(pci->table_group, - pci_domain_nr(pci->phb->bus), 0); + pci_domain_nr(bridge->bus), 0); pr_debug(" created table: %p\n", pci->table_group); } else { pr_debug(" found DMA window, table: %p\n", pci->table_group); diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 1bffbd1c9a94b..038fd1d3fd946 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -317,10 +317,6 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) bus = bridge->bus; - /* Rely on the pcibios_free_controller_deferred() callback. */ - pci_set_host_bridge_release(bridge, pcibios_free_controller_deferred, - (void *) pci_bus_to_host(bus)); - dn = pcibios_get_phb_of_node(bus); if (!dn) return 0; diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index f9ae17e8a0f46..a2fdb234134fb 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -21,12 +21,14 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) { struct pci_controller *phb; + struct pci_host_bridge *bridge; pr_debug("PCI: Initializing new hotplug PHB %pOF\n", dn); phb = pcibios_alloc_controller(dn); if (!phb) return NULL; + bridge = phb->bridge; rtas_setup_phb(phb); pci_process_bridge_OF_ranges(phb, dn, 0); phb->controller_ops = pseries_pci_controller_ops; @@ -39,8 +41,8 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) if (dn->child) pseries_eeh_init_edev_recursive(PCI_DN(dn)); - pcibios_scan_phb(phb); - pcibios_finish_adding_to_bus(phb->bus); + pcibios_scan_host_bridge(bridge); + pcibios_finish_adding_to_bus(bridge->bus); return phb; } @@ -49,15 +51,16 @@ EXPORT_SYMBOL_GPL(init_phb_dynamic); /* RPA-specific bits for removing PHBs */ int remove_phb_dynamic(struct pci_controller *phb) { - struct pci_bus *b = phb->bus; + struct pci_host_bridge *bridge = phb->bridge; struct resource *res; int rc, i; pr_debug("PCI: Removing PHB %04x:%02x...\n", - pci_domain_nr(b), b->number); + pci_domain_nr(bridge->bus), bridge->busnr); /* We cannot to remove a root bus that has children */ - if (!(list_empty(&b->children) && list_empty(&b->devices))) + if (!(list_empty(&bridge->bus->children) && + list_empty(&bridge->bus->devices))) return -EBUSY; /* We -know- there aren't any child devices anymore at this stage @@ -65,18 +68,16 @@ int remove_phb_dynamic(struct pci_controller *phb) */ res = &phb->io_resource; if (res->flags & IORESOURCE_IO) { - rc = pcibios_unmap_io_space(b); + rc = pcibios_unmap_io_space(bridge->bus); if (rc) { printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", - __func__, b->name); + __func__, bridge->bus->name); return 1; } } /* Remove the PCI bus and unregister the bridge device from sysfs */ - phb->bus = NULL; - pci_remove_bus(b); - device_unregister(b->bridge); + pci_remove_bus(bridge->bus); /* Now release the IO resource */ if (res->flags & IORESOURCE_IO) @@ -90,11 +91,7 @@ int remove_phb_dynamic(struct pci_controller *phb) release_resource(res); } - /* - * The pci_controller data structure is freed by - * the pcibios_free_controller_deferred() callback; - * see pseries_root_bridge_prepare(). - */ + device_unregister(&bridge->dev); return 0; } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 46e1540abc229..262e233c1160e 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -474,7 +474,7 @@ static void __init pSeries_discover_phbs(void) !of_node_is_type(node, "pciex")) continue; - phb = pcibios_alloc_controller(node); + phb = pcibios_alloc_controller_early(node); if (!phb) continue; rtas_setup_phb(phb); diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 040b9d01c0798..989e7083332ba 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -68,7 +68,7 @@ static int fsl_pcie_check_link(struct pci_controller *hose) u32 val = 0; if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose->ops->read == fsl_indirect_read_config) + if (hose->bridge->ops->read == fsl_indirect_read_config) __indirect_read_config(hose, hose->first_busno, 0, PCIE_LTSSM, 4, &val); else @@ -493,7 +493,7 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK); - if (bus->parent == hose->bus && (is_pcie || no_link)) { + if (bus->parent == hose->bridge->bus && (is_pcie || no_link)) { for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) { struct resource *res = bus->resource[i]; struct resource *par; @@ -552,7 +552,7 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary) return -ENOMEM; /* set platform device as the parent */ - hose->parent = &pdev->dev; + hose->bridge->dev.parent = &pdev->dev; hose->first_busno = bus_range ? bus_range[0] : 0x0; hose->last_busno = bus_range ? bus_range[1] : 0xff; @@ -571,7 +571,7 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary) if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { /* use fsl_indirect_read_config for PCIe */ - hose->ops = &fsl_indirect_pcie_ops; + hose->bridge->ops = &fsl_indirect_pcie_ops; /* For PCIE read HEADER_TYPE to identify controller mode */ early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) @@ -774,7 +774,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose, WARN_ON(hose->dn->data); hose->dn->data = pcie; - hose->ops = &mpc83xx_pcie_ops; + hose->bridge->ops = &mpc83xx_pcie_ops; hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK; out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0); @@ -912,7 +912,7 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose) if (!is_mpc83xx_pci) { u32 base; - pci_bus_read_config_dword(hose->bus, + pci_bus_read_config_dword(hose->bridge->bus, PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); /* @@ -1163,7 +1163,8 @@ static int fsl_pci_pme_probe(struct pci_controller *hose) u16 pms; /* Get hose's pci_dev */ - dev = list_first_entry(&hose->bus->devices, typeof(*dev), bus_list); + dev = list_first_entry(&hose->bridge->bus->devices, + typeof(*dev), bus_list); /* PME Disable */ pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pms); @@ -1177,7 +1178,7 @@ static int fsl_pci_pme_probe(struct pci_controller *hose) return -ENXIO; } - res = devm_request_irq(hose->parent, pme_irq, + res = devm_request_irq(hose->bridge->dev.parent, pme_irq, fsl_pci_pme_handle, IRQF_SHARED, "[PCI] PME", hose); diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index 09b36617425ea..f8eda799a4253 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c @@ -168,6 +168,6 @@ void setup_indirect_pci(struct pci_controller *hose, resource_size_t cfg_addr, if ((cfg_data & PAGE_MASK) != base) mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK); - hose->ops = &indirect_pci_ops; + hose->bridge->ops = &indirect_pci_ops; hose->indirect_type = flags; } diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 49f9541954f8d..4b19486e1e5db 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -204,7 +204,7 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) " bus 0\n", dev); } - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller_early(dev); if (!hose) { printk("PCI Host bridge init failed\n"); @@ -214,7 +214,7 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - (hose)->ops = &tsi108_direct_pci_ops; + hose->bridge->ops = &tsi108_direct_pci_ops; printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. " "Firmware bus number: %d->%d\n", diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c index 186308f1f8eba..240f551067759 100644 --- a/drivers/misc/cxl/guest.c +++ b/drivers/misc/cxl/guest.c @@ -24,7 +24,7 @@ static void pci_error_handlers(struct cxl_afu *afu, if (afu->phb == NULL) return; - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { + list_for_each_entry(afu_dev, &afu->phb->bridge->bus->devices, bus_list) { if (!afu_dev->driver) continue; diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 2ba899f5659ff..ca2c8f59102ce 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1804,7 +1804,7 @@ static pci_ers_result_t cxl_vphb_error_detected(struct cxl_afu *afu, if (afu == NULL || afu->phb == NULL) return result; - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { + list_for_each_entry(afu_dev, &afu->phb->bridge->bus->devices, bus_list) { if (!afu_dev->driver) continue; @@ -2002,7 +2002,8 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev) if (afu->phb == NULL) continue; - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { + list_for_each_entry(afu_dev, &afu->phb->bridge->bus->devices, + bus_list) { /* Reset the device context. * TODO: make this less disruptive */ @@ -2073,7 +2074,7 @@ static void cxl_pci_resume(struct pci_dev *pdev) if (afu == NULL || afu->phb == NULL) continue; - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { + list_for_each_entry(afu_dev, &afu->phb->bridge->bus->devices, bus_list) { if (afu_dev->driver && afu_dev->driver->err_handler && afu_dev->driver->err_handler->resume) afu_dev->driver->err_handler->resume(afu_dev); diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index 1264253cc07bc..de3ea38061157 100644 --- a/drivers/misc/cxl/vphb.c +++ b/drivers/misc/cxl/vphb.c @@ -208,6 +208,7 @@ static struct pci_controller_ops cxl_pci_controller_ops = int cxl_pci_vphb_add(struct cxl_afu *afu) { + struct pci_host_bridge *bridge; struct pci_controller *phb; struct device_node *vphb_dn; struct device *parent; @@ -238,34 +239,30 @@ int cxl_pci_vphb_add(struct cxl_afu *afu) if (!phb) return -ENODEV; - /* Setup parent in sysfs */ - phb->parent = parent; + /* Setup bridge */ + bridge = phb->bridge; + bridge->dev.parent = parent; + bridge->ops = &cxl_pcie_pci_ops; /* Setup the PHB using arch provided callback */ - phb->ops = &cxl_pcie_pci_ops; phb->cfg_addr = NULL; phb->cfg_data = NULL; phb->private_data = afu; phb->controller_ops = cxl_pci_controller_ops; /* Scan the bus */ - pcibios_scan_phb(phb); - if (phb->bus == NULL) + pcibios_scan_host_bridge(bridge); + if (bridge->bus == NULL) return -ENXIO; - /* Set release hook on root bus */ - pci_set_host_bridge_release(to_pci_host_bridge(phb->bus->bridge), - pcibios_free_controller_deferred, - (void *) phb); - /* Claim resources. This might need some rework as well depending * whether we are doing probe-only or not, like assigning unassigned * resources etc... */ - pcibios_claim_one_bus(phb->bus); + pcibios_claim_one_bus(bridge->bus); /* Add probed PCI devices to the device model */ - pci_bus_add_devices(phb->bus); + pci_bus_add_devices(bridge->bus); afu->phb = phb; @@ -283,11 +280,7 @@ void cxl_pci_vphb_remove(struct cxl_afu *afu) phb = afu->phb; afu->phb = NULL; - pci_remove_root_bus(phb->bus); - /* - * We don't free phb here - that's handled by - * pcibios_free_controller_deferred() - */ + pci_remove_root_bus(phb->bridge->bus); } bool cxl_pci_is_vphb_device(struct pci_dev *dev) @@ -296,7 +289,7 @@ bool cxl_pci_is_vphb_device(struct pci_dev *dev) phb = pci_bus_to_host(dev->bus); - return (phb->ops == &cxl_pcie_pci_ops); + return (phb->bridge->ops == &cxl_pcie_pci_ops); } struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev) diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 0a3c80ba66be4..fee51078c0679 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -137,13 +137,13 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, static void dlpar_pci_add_bus(struct device_node *dn) { struct pci_dn *pdn = PCI_DN(dn); - struct pci_controller *phb = pdn->phb; + struct pci_host_bridge *bridge = pdn->phb->bridge; struct pci_dev *dev = NULL; pseries_eeh_init_edev_recursive(pdn); /* Add EADS device to PHB bus, adding new entry to bus->devices */ - dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); + dev = of_create_pci_dev(dn, bridge->bus, pdn->devfn); if (!dev) { printk(KERN_ERR "%s: failed to create pci dev for %pOF\n", __func__, dn); @@ -162,13 +162,13 @@ static void dlpar_pci_add_bus(struct device_node *dn) * bus of the EADS bridge so the bridge device itself gets * properly added */ - pcibios_finish_adding_to_bus(phb->bus); + pcibios_finish_adding_to_bus(bridge->bus); } static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; - struct pci_controller *phb; + struct pci_host_bridge *bridge; if (pci_find_bus_by_node(dn)) return -EINVAL; @@ -177,8 +177,8 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) dlpar_pci_add_bus(dn); /* Confirm new bridge dev was created */ - phb = PCI_DN(dn)->phb; - dev = dlpar_find_new_dev(phb->bus, dn); + bridge = PCI_DN(dn)->phb->bridge; + dev = dlpar_find_new_dev(bridge->bus, dn); if (!dev) { printk(KERN_ERR "%s: unable to add bus %s\n", __func__, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a599ee482e01d..33bb277dbb1f4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -570,7 +570,7 @@ static void pci_release_host_bridge_dev(struct device *dev) kfree(bridge); } -static void pci_init_host_bridge(struct pci_host_bridge *bridge) +void pci_init_host_bridge(struct pci_host_bridge *bridge) { INIT_LIST_HEAD(&bridge->windows); INIT_LIST_HEAD(&bridge->dma_ranges); diff --git a/include/linux/pci.h b/include/linux/pci.h index 99fbfef9bdec8..b677e686a3535 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -574,6 +574,7 @@ static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv) return container_of(priv, struct pci_host_bridge, private); } +void pci_init_host_bridge(struct pci_host_bridge *bridge); struct pci_host_bridge *pci_alloc_host_bridge(size_t priv); struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev, size_t priv); |
