Commit 26ba248d authored by Gavin Shan's avatar Gavin Shan Committed by Michael Ellerman

powerpc/powernv: Pick M64 PEs based on BARs

On PHB3, PE might be reserved in advance to reflect the M64 segments
consumed by the PE according to M64 BARs (exclude VF BARs) of the PCI
devices included in the PE. The PE is picked based on M64 BARs instead
of the bridge's M64 windows, which might include VF BARs. Otherwise,
wrong PE could be picked.

The patch calculates the used M64 segments and PE numbers according to
the M64 BARs, excluding VF BARs, of PCI devices in one particular PE,
instead of the bridge's M64 windows. Then the right PE number is picked.
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent d1203852
...@@ -271,35 +271,18 @@ static void pnv_ioda2_reserve_m64_pe(struct pci_bus *bus, ...@@ -271,35 +271,18 @@ static void pnv_ioda2_reserve_m64_pe(struct pci_bus *bus,
} }
} }
static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb, static int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all)
struct pci_bus *bus, bool all)
{ {
resource_size_t segsz = phb->ioda.m64_segsize; struct pci_controller *hose = pci_bus_to_host(bus);
struct pci_dev *pdev; struct pnv_phb *phb = hose->private_data;
struct resource *r;
struct pnv_ioda_pe *master_pe, *pe; struct pnv_ioda_pe *master_pe, *pe;
unsigned long size, *pe_alloc; unsigned long size, *pe_alloc;
bool found; int i;
int start, i, j;
/* Root bus shouldn't use M64 */ /* Root bus shouldn't use M64 */
if (pci_is_root_bus(bus)) if (pci_is_root_bus(bus))
return IODA_INVALID_PE; return IODA_INVALID_PE;
/* We support only one M64 window on each bus */
found = false;
pci_bus_for_each_resource(bus, r, i) {
if (r && r->parent &&
pnv_pci_is_mem_pref_64(r->flags)) {
found = true;
break;
}
}
/* No M64 window found ? */
if (!found)
return IODA_INVALID_PE;
/* Allocate bitmap */ /* Allocate bitmap */
size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long)); size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
pe_alloc = kzalloc(size, GFP_KERNEL); pe_alloc = kzalloc(size, GFP_KERNEL);
...@@ -309,35 +292,8 @@ static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb, ...@@ -309,35 +292,8 @@ static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb,
return IODA_INVALID_PE; return IODA_INVALID_PE;
} }
/* /* Figure out reserved PE numbers by the PE */
* Figure out reserved PE numbers by the PE pnv_ioda2_reserve_m64_pe(bus, pe_alloc, all);
* the its child PEs.
*/
start = (r->start - phb->ioda.m64_base) / segsz;
for (i = 0; i < resource_size(r) / segsz; i++)
set_bit(start + i, pe_alloc);
if (all)
goto done;
/*
* If the PE doesn't cover all subordinate buses,
* we need subtract from reserved PEs for children.
*/
list_for_each_entry(pdev, &bus->devices, bus_list) {
if (!pdev->subordinate)
continue;
pci_bus_for_each_resource(pdev->subordinate, r, i) {
if (!r || !r->parent ||
!pnv_pci_is_mem_pref_64(r->flags))
continue;
start = (r->start - phb->ioda.m64_base) / segsz;
for (j = 0; j < resource_size(r) / segsz ; j++)
clear_bit(start + j, pe_alloc);
}
}
/* /*
* the current bus might not own M64 window and that's all * the current bus might not own M64 window and that's all
...@@ -353,7 +309,6 @@ static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb, ...@@ -353,7 +309,6 @@ static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb,
* Figure out the master PE and put all slave PEs to master * Figure out the master PE and put all slave PEs to master
* PE's list to form compound PE. * PE's list to form compound PE.
*/ */
done:
master_pe = NULL; master_pe = NULL;
i = -1; i = -1;
while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) < while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) <
...@@ -1073,7 +1028,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) ...@@ -1073,7 +1028,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)
/* Check if PE is determined by M64 */ /* Check if PE is determined by M64 */
if (phb->pick_m64_pe) if (phb->pick_m64_pe)
pe_num = phb->pick_m64_pe(phb, bus, all); pe_num = phb->pick_m64_pe(bus, all);
/* The PE number isn't pinned by M64 */ /* The PE number isn't pinned by M64 */
if (pe_num == IODA_INVALID_PE) if (pe_num == IODA_INVALID_PE)
......
...@@ -112,7 +112,7 @@ struct pnv_phb { ...@@ -112,7 +112,7 @@ struct pnv_phb {
int (*init_m64)(struct pnv_phb *phb); int (*init_m64)(struct pnv_phb *phb);
void (*reserve_m64_pe)(struct pci_bus *bus, void (*reserve_m64_pe)(struct pci_bus *bus,
unsigned long *pe_bitmap, bool all); unsigned long *pe_bitmap, bool all);
int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, bool all); int (*pick_m64_pe)(struct pci_bus *bus, bool all);
int (*get_pe_state)(struct pnv_phb *phb, int pe_no); int (*get_pe_state)(struct pnv_phb *phb, int pe_no);
void (*freeze_pe)(struct pnv_phb *phb, int pe_no); void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt); int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment