diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-17 10:07:43 +0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-17 10:07:43 +0400 |
commit | eda485f06d17f98bd58559fb5dd331951ffd1608 (patch) | |
tree | c76f119e68734932c6751cd14fdd420544da92c3 /arch/powerpc | |
parent | 6b5e7229bbd59f0cfce7015fd46736fc93d8c8c3 (diff) | |
parent | 9a5d5bd8480068c5829e3d997ee21dab9b3ed05f (diff) | |
download | linux-eda485f06d17f98bd58559fb5dd331951ffd1608.tar.xz |
Merge remote-tracking branch 'pci/pci/gavin-window-alignment' into next
Merge Gavin patches from the PCI tree as subsequent powerpc
patches are going to depend on them
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/machdep.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 20 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 41 |
3 files changed, 63 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 236b4779ec4f..8111e1b78f7f 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -215,6 +215,9 @@ struct machdep_calls { /* Called after scan and before resource survey */ void (*pcibios_fixup_phb)(struct pci_controller *hose); + /* Called during PCI resource reassignment */ + resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type); + /* Called to shutdown machine specific hardware not already controlled * by other drivers. */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 4cb714792bea..7f94f760dd0c 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -99,6 +99,26 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } +/* + * The function is used to return the minimal alignment + * for memory or I/O windows of the associated P2P bridge. + * By default, 4KiB alignment for I/O windows and 1MiB for + * memory windows. + */ +resource_size_t pcibios_window_alignment(struct pci_bus *bus, + unsigned long type) +{ + if (ppc_md.pcibios_window_alignment) + return ppc_md.pcibios_window_alignment(bus, type); + + /* + * PCI core will figure out the default + * alignment: 4KiB for I/O and 1MiB for + * memory window. + */ + return 1; +} + static resource_size_t pcibios_io_size(const struct pci_controller *hose) { #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 5e75dcfe51b9..cae7281e4e66 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -854,7 +854,7 @@ static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus) if (pe == NULL) continue; /* Leaving the PCIe domain ... single PE# */ - if (dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) pnv_ioda_setup_bus_PE(dev, pe); else if (dev->subordinate) pnv_ioda_setup_PEs(dev->subordinate); @@ -1138,6 +1138,44 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose) } } +/* + * Returns the alignment for I/O or memory windows for P2P + * bridges. That actually depends on how PEs are segmented. + * For now, we return I/O or M32 segment size for PE sensitive + * P2P bridges. Otherwise, the default values (4KiB for I/O, + * 1MiB for memory) will be returned. + * + * The current PCI bus might be put into one PE, which was + * create against the parent PCI bridge. For that case, we + * needn't enlarge the alignment so that we can save some + * resources. + */ +static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, + unsigned long type) +{ + struct pci_dev *bridge; + struct pci_controller *hose = pci_bus_to_host(bus); + struct pnv_phb *phb = hose->private_data; + int num_pci_bridges = 0; + + bridge = bus->self; + while (bridge) { + if (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) { + num_pci_bridges++; + if (num_pci_bridges >= 2) + return 1; + } + + bridge = bridge->bus->self; + } + + /* We need support prefetchable memory window later */ + if (type & IORESOURCE_MEM) + return phb->ioda.m32_segsize; + + return phb->ioda.io_segsize; +} + /* Prevent enabling devices for which we couldn't properly * assign a PE */ @@ -1305,6 +1343,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np) */ ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb; ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; + ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC); /* Reset IODA tables to a clean state */ |