diff options
author | Wei Yang <weiyang@linux.vnet.ibm.com> | 2015-03-25 04:23:55 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-03-30 22:02:37 -0400 |
commit | 6e628c7d33d99406cef374972c89389edcc3570f (patch) | |
tree | 21a6a79faa895cd26f5127dfaba7b3423b2ae409 | |
parent | 9e8d4a19ab66ec9e132d405357b9108a4f26efd3 (diff) |
powerpc/powernv: Reserve additional space for IOV BAR according to the number of total_pe
On PHB3, PF IOV BAR will be covered by M64 BAR to have better PE isolation.
M64 BAR is a type of hardware resource in PHB3, which could map a range of
MMIO to PE numbers on powernv platform. And this range is divided equally
by the number of total_pe with each divided range mapping to a PE number.
Also, the M64 BAR must map a MMIO range with power-of-two size.
The total_pe number is usually different from total_VFs, which can lead to
a conflict between MMIO space and the PE number.
For example, if total_VFs is 128 and total_pe is 256, the second half of
M64 BAR will be part of other PCI device, which may already belong to other
PEs.
This patch prevents the conflict by reserving additional space for the PF
IOV BAR, which is total_pe number of VF's BAR size.
[bhelgaas: make dev_printk() output more consistent, index resource[]
conventionally]
Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/include/asm/machdep.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pci-bridge.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 43 |
4 files changed, 56 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 098d51e924ea..b303833fa3fb 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -250,6 +250,10 @@ struct machdep_calls { | |||
250 | /* Reset the secondary bus of bridge */ | 250 | /* Reset the secondary bus of bridge */ |
251 | void (*pcibios_reset_secondary_bus)(struct pci_dev *dev); | 251 | void (*pcibios_reset_secondary_bus)(struct pci_dev *dev); |
252 | 252 | ||
253 | #ifdef CONFIG_PCI_IOV | ||
254 | void (*pcibios_fixup_sriov)(struct pci_dev *pdev); | ||
255 | #endif /* CONFIG_PCI_IOV */ | ||
256 | |||
253 | /* Called to shutdown machine specific hardware not already controlled | 257 | /* Called to shutdown machine specific hardware not already controlled |
254 | * by other drivers. | 258 | * by other drivers. |
255 | */ | 259 | */ |
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ece30f589398..7b8ebc5929ff 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
@@ -178,6 +178,9 @@ struct pci_dn { | |||
178 | #define IODA_INVALID_PE (-1) | 178 | #define IODA_INVALID_PE (-1) |
179 | #ifdef CONFIG_PPC_POWERNV | 179 | #ifdef CONFIG_PPC_POWERNV |
180 | int pe_number; | 180 | int pe_number; |
181 | #ifdef CONFIG_PCI_IOV | ||
182 | u16 vfs_expanded; /* number of VFs IOV BAR expanded */ | ||
183 | #endif /* CONFIG_PCI_IOV */ | ||
181 | #endif | 184 | #endif |
182 | struct list_head child_list; | 185 | struct list_head child_list; |
183 | struct list_head list; | 186 | struct list_head list; |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 82031011522f..375bf7099912 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -990,6 +990,12 @@ int pcibios_add_device(struct pci_dev *dev) | |||
990 | */ | 990 | */ |
991 | if (dev->bus->is_added) | 991 | if (dev->bus->is_added) |
992 | pcibios_setup_device(dev); | 992 | pcibios_setup_device(dev); |
993 | |||
994 | #ifdef CONFIG_PCI_IOV | ||
995 | if (ppc_md.pcibios_fixup_sriov) | ||
996 | ppc_md.pcibios_fixup_sriov(dev); | ||
997 | #endif /* CONFIG_PCI_IOV */ | ||
998 | |||
993 | return 0; | 999 | return 0; |
994 | } | 1000 | } |
995 | 1001 | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9447ee9b4aa3..1da45aa76a03 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -1749,6 +1749,46 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) | |||
1749 | static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { } | 1749 | static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { } |
1750 | #endif /* CONFIG_PCI_MSI */ | 1750 | #endif /* CONFIG_PCI_MSI */ |
1751 | 1751 | ||
1752 | #ifdef CONFIG_PCI_IOV | ||
1753 | static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) | ||
1754 | { | ||
1755 | struct pci_controller *hose; | ||
1756 | struct pnv_phb *phb; | ||
1757 | struct resource *res; | ||
1758 | int i; | ||
1759 | resource_size_t size; | ||
1760 | struct pci_dn *pdn; | ||
1761 | |||
1762 | if (!pdev->is_physfn || pdev->is_added) | ||
1763 | return; | ||
1764 | |||
1765 | hose = pci_bus_to_host(pdev->bus); | ||
1766 | phb = hose->private_data; | ||
1767 | |||
1768 | pdn = pci_get_pdn(pdev); | ||
1769 | pdn->vfs_expanded = 0; | ||
1770 | |||
1771 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
1772 | res = &pdev->resource[i + PCI_IOV_RESOURCES]; | ||
1773 | if (!res->flags || res->parent) | ||
1774 | continue; | ||
1775 | if (!pnv_pci_is_mem_pref_64(res->flags)) { | ||
1776 | dev_warn(&pdev->dev, "Skipping expanding VF BAR%d: %pR\n", | ||
1777 | i, res); | ||
1778 | continue; | ||
1779 | } | ||
1780 | |||
1781 | dev_dbg(&pdev->dev, " Fixing VF BAR%d: %pR to\n", i, res); | ||
1782 | size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); | ||
1783 | res->end = res->start + size * phb->ioda.total_pe - 1; | ||
1784 | dev_dbg(&pdev->dev, " %pR\n", res); | ||
1785 | dev_info(&pdev->dev, "VF BAR%d: %pR (expanded to %d VFs for PE alignment)", | ||
1786 | i, res, phb->ioda.total_pe); | ||
1787 | } | ||
1788 | pdn->vfs_expanded = phb->ioda.total_pe; | ||
1789 | } | ||
1790 | #endif /* CONFIG_PCI_IOV */ | ||
1791 | |||
1752 | /* | 1792 | /* |
1753 | * This function is supposed to be called on basis of PE from top | 1793 | * This function is supposed to be called on basis of PE from top |
1754 | * to bottom style. So the the I/O or MMIO segment assigned to | 1794 | * to bottom style. So the the I/O or MMIO segment assigned to |
@@ -2122,6 +2162,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
2122 | ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; | 2162 | ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; |
2123 | ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; | 2163 | ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; |
2124 | ppc_md.pcibios_reset_secondary_bus = pnv_pci_reset_secondary_bus; | 2164 | ppc_md.pcibios_reset_secondary_bus = pnv_pci_reset_secondary_bus; |
2165 | #ifdef CONFIG_PCI_IOV | ||
2166 | ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources; | ||
2167 | #endif /* CONFIG_PCI_IOV */ | ||
2125 | pci_add_flags(PCI_REASSIGN_ALL_RSRC); | 2168 | pci_add_flags(PCI_REASSIGN_ALL_RSRC); |
2126 | 2169 | ||
2127 | /* Reset IODA tables to a clean state */ | 2170 | /* Reset IODA tables to a clean state */ |