powerpc/pnv/pci: Fix incorrect PE reservation attempt on some 64-bit BARs
The generic allocation code may sometimes decide to assign a prefetchable 64-bit BAR to the M32 window. In fact it may also decide to allocate a 64-bit non-prefetchable BAR to the M64 one ! So using the resource flags as a test to decide which window was used for PE allocation is just wrong and leads to insane PE numbers. Instead, compare the addresses to figure it out. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [mpe: Rename the function as agreed by Ben & Gavin] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
c74dd88e77
commit
5958d19a14
@ -111,10 +111,17 @@ static int __init iommu_setup(char *str)
|
|||||||
}
|
}
|
||||||
early_param("iommu", iommu_setup);
|
early_param("iommu", iommu_setup);
|
||||||
|
|
||||||
static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
|
static inline bool pnv_pci_is_m64(struct pnv_phb *phb, struct resource *r)
|
||||||
{
|
{
|
||||||
return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
|
/*
|
||||||
(IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
|
* WARNING: We cannot rely on the resource flags. The Linux PCI
|
||||||
|
* allocation code sometimes decides to put a 64-bit prefetchable
|
||||||
|
* BAR in the 32-bit window, so we have to compare the addresses.
|
||||||
|
*
|
||||||
|
* For simplicity we only test resource start.
|
||||||
|
*/
|
||||||
|
return (r->start >= phb->ioda.m64_base &&
|
||||||
|
r->start < (phb->ioda.m64_base + phb->ioda.m64_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
|
static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
|
||||||
@ -229,7 +236,7 @@ static void pnv_ioda_reserve_dev_m64_pe(struct pci_dev *pdev,
|
|||||||
sgsz = phb->ioda.m64_segsize;
|
sgsz = phb->ioda.m64_segsize;
|
||||||
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
|
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
|
||||||
r = &pdev->resource[i];
|
r = &pdev->resource[i];
|
||||||
if (!r->parent || !pnv_pci_is_mem_pref_64(r->flags))
|
if (!r->parent || !pnv_pci_is_m64(phb, r))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
start = _ALIGN_DOWN(r->start - base, sgsz);
|
start = _ALIGN_DOWN(r->start - base, sgsz);
|
||||||
@ -2863,7 +2870,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
|
|||||||
res = &pdev->resource[i + PCI_IOV_RESOURCES];
|
res = &pdev->resource[i + PCI_IOV_RESOURCES];
|
||||||
if (!res->flags || res->parent)
|
if (!res->flags || res->parent)
|
||||||
continue;
|
continue;
|
||||||
if (!pnv_pci_is_mem_pref_64(res->flags)) {
|
if (!pnv_pci_is_m64(phb, res)) {
|
||||||
dev_warn(&pdev->dev, "Don't support SR-IOV with"
|
dev_warn(&pdev->dev, "Don't support SR-IOV with"
|
||||||
" non M64 VF BAR%d: %pR. \n",
|
" non M64 VF BAR%d: %pR. \n",
|
||||||
i, res);
|
i, res);
|
||||||
@ -2958,7 +2965,7 @@ static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
} else if ((res->flags & IORESOURCE_MEM) &&
|
} else if ((res->flags & IORESOURCE_MEM) &&
|
||||||
!pnv_pci_is_mem_pref_64(res->flags)) {
|
!pnv_pci_is_m64(phb, res)) {
|
||||||
region.start = res->start -
|
region.start = res->start -
|
||||||
phb->hose->mem_offset[0] -
|
phb->hose->mem_offset[0] -
|
||||||
phb->ioda.m32_pci_base;
|
phb->ioda.m32_pci_base;
|
||||||
@ -3083,9 +3090,12 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
|
|||||||
bridge = bridge->bus->self;
|
bridge = bridge->bus->self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We fail back to M32 if M64 isn't supported */
|
/*
|
||||||
if (phb->ioda.m64_segsize &&
|
* We fall back to M32 if M64 isn't supported. We enforce the M64
|
||||||
pnv_pci_is_mem_pref_64(type))
|
* alignment for any 64-bit resource, PCIe doesn't care and
|
||||||
|
* bridges only do 64-bit prefetchable anyway.
|
||||||
|
*/
|
||||||
|
if (phb->ioda.m64_segsize && (type & IORESOURCE_MEM_64))
|
||||||
return phb->ioda.m64_segsize;
|
return phb->ioda.m64_segsize;
|
||||||
if (type & IORESOURCE_MEM)
|
if (type & IORESOURCE_MEM)
|
||||||
return phb->ioda.m32_segsize;
|
return phb->ioda.m32_segsize;
|
||||||
@ -3125,7 +3135,7 @@ static void pnv_pci_fixup_bridge_resources(struct pci_bus *bus,
|
|||||||
w = NULL;
|
w = NULL;
|
||||||
if (r->flags & type & IORESOURCE_IO)
|
if (r->flags & type & IORESOURCE_IO)
|
||||||
w = &hose->io_resource;
|
w = &hose->io_resource;
|
||||||
else if (pnv_pci_is_mem_pref_64(r->flags) &&
|
else if (pnv_pci_is_m64(phb, r) &&
|
||||||
(type & IORESOURCE_PREFETCH) &&
|
(type & IORESOURCE_PREFETCH) &&
|
||||||
phb->ioda.m64_segsize)
|
phb->ioda.m64_segsize)
|
||||||
w = &hose->mem_resources[1];
|
w = &hose->mem_resources[1];
|
||||||
|
Loading…
Reference in New Issue
Block a user