aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2020-12-19 18:01:52 +0100
committerArnd Bergmann <arnd@arndb.de>2021-03-20 17:02:16 +0100
commit3b0acc0ac3c7dc0ecb99215c7eb87a41a4acd79f (patch)
tree2300b1abc93141aaf52bb639249c2a0d0261f42e
parent1c9bc5ddbff8a4399597ecba68dc47ec2fb41679 (diff)
downloadplayground-3b0acc0ac3c7dc0ecb99215c7eb87a41a4acd79f.tar.gz
powerpc: rework PCI host allocation
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h5
-rw-r--r--arch/powerpc/include/asm/pci.h2
-rw-r--r--arch/powerpc/kernel/eeh_pe.c3
-rw-r--r--arch/powerpc/kernel/of_platform.c12
-rw-r--r--arch/powerpc/kernel/pci-common.c134
-rw-r--r--arch/powerpc/kernel/pci-hotplug.c4
-rw-r--r--arch/powerpc/kernel/pci_32.c6
-rw-r--r--arch/powerpc/kernel/pci_64.c4
-rw-r--r--arch/powerpc/kernel/rtas_pci.c2
-rw-r--r--arch/powerpc/platforms/4xx/pci.c2
-rw-r--r--arch/powerpc/platforms/52xx/efika.c4
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c4
-rw-r--r--arch/powerpc/platforms/82xx/pq2.c2
-rw-r--r--arch/powerpc/platforms/amigaone/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spider-pci.c8
-rw-r--r--arch/powerpc/platforms/chrp/pci.c8
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/mvme5100.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c2
-rw-r--r--arch/powerpc/platforms/maple/pci.c8
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c4
-rw-r--r--arch/powerpc/platforms/powermac/pci.c14
-rw-r--r--arch/powerpc/platforms/powernv/npu-dma.c6
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c11
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c10
-rw-r--r--arch/powerpc/platforms/pseries/pci.c4
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c27
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c17
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c2
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c4
-rw-r--r--drivers/misc/cxl/guest.c2
-rw-r--r--drivers/misc/cxl/pci.c7
-rw-r--r--drivers/misc/cxl/vphb.c29
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c12
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--include/linux/pci.h1
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 = &macrisc_pci_ops;
+ hose->bridge->ops = &macrisc_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 = &macrisc_pci_ops;
+ hose->bridge->ops = &macrisc_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 = &macrisc_pci_ops;
+ hose->bridge->ops = &macrisc_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);