Removed the assumption that the system has only one primary root bus. When mapping memory and IO regions go over all buses, skipping secondary and absent buses.
Signed-off-by: Marcel Apfelbaum marcel.a@redhat.com --- src/fw/pciinit.c | 114 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 35 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index a5f6505..97b1af6 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -763,43 +763,80 @@ static int pci_bios_init_root_regions_io(struct pci_bus *bus) * where they want, on older versions its fixed ] * c000 - ffff free, traditionally used for pci io */ - struct pci_region *r_io = &bus->r[PCI_REGION_TYPE_IO]; - u64 sum = pci_region_sum(r_io); - if (sum < 0x4000) { - /* traditional region is big enougth, use it */ - r_io->base = 0xc000; - } else if (sum < pci_io_low_end - 0x1000) { - /* use the larger region at 0x1000 */ - r_io->base = 0x1000; - } else { - /* not enouth io address space -> error out */ - return -1; + + u64 sum_pci = 0; /* c000 - ffff */ + u64 sum_free = 0; /* 1000 - 9fff */ + int i; + + for (i = 0; i <= MaxPCIBus; i++) { + struct pci_region *r_io = &bus[i].r[PCI_REGION_TYPE_IO]; + u64 sum = pci_region_sum(r_io); + if (bus[i].bus_dev || !sum) + continue; + + sum_pci = ALIGN(sum_pci, sum); + sum_free = ALIGN(sum_free, sum); + if (sum + sum_pci < 0x4000) { + /* traditional region is big enough, use it */ + r_io->base = 0xc000 + sum_pci; + sum_pci += sum; + } else if (sum < pci_io_low_end - 0x1000 - sum_free) { + /* use the larger region at 0x1000 */ + r_io->base = 0x1000 + sum_free; + sum_free += sum; + } else { + /* not enough io address space -> error out */ + return -1; + } + + if (sum) { + dprintf(1, "PCI: BUS %d IO: %4llx - %4llx\n", + i, r_io->base, r_io->base + sum - 1); + } } - dprintf(1, "PCI: IO: %4llx - %4llx\n", r_io->base, r_io->base + sum - 1); return 0; }
static int pci_bios_init_root_regions_mem(struct pci_bus *bus) { - struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM]; - struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM]; - - if (pci_region_align(r_start) < pci_region_align(r_end)) { - // Swap regions to improve alignment. - r_end = r_start; - r_start = &bus->r[PCI_REGION_TYPE_PREFMEM]; - } - u64 sum = pci_region_sum(r_end); - u64 align = pci_region_align(r_end); - r_end->base = ALIGN_DOWN((pcimem_end - sum), align); - sum = pci_region_sum(r_start); - align = pci_region_align(r_start); - r_start->base = ALIGN_DOWN((r_end->base - sum), align); - - if ((r_start->base < pcimem_start) || - (r_start->base > pcimem_end)) - // Memory range requested is larger than available. - return -1; + u64 region_end = pcimem_end; + int i; + + for (i = 0; i <= MaxPCIBus; i++) { + struct pci_region *r_end = &bus[i].r[PCI_REGION_TYPE_PREFMEM]; + struct pci_region *r_start = &bus[i].r[PCI_REGION_TYPE_MEM]; + + if (pci_region_align(r_start) < pci_region_align(r_end)) { + // Swap regions to improve alignment. + r_end = r_start; + r_start = &bus[i].r[PCI_REGION_TYPE_PREFMEM]; + } + + u64 sum = pci_region_sum(r_end); + if (bus[i].bus_dev || !sum) + continue; + + u64 align = pci_region_align(r_end); + r_end->base = ALIGN_DOWN((region_end - sum), align); + + dprintf(1, "PCI: BUS %d MEM: %4llx - %4llx\n", + i, r_end->base, r_end->base + sum - 1); + + sum = pci_region_sum(r_start); + align = pci_region_align(r_start); + r_start->base = ALIGN_DOWN((r_end->base - sum), align); + region_end = r_start->base; + + dprintf(1, "PCI: BUS %d MEM: %4llx - %4llx\n", + i, r_start->base, r_start->base + sum - 1); + + if ((r_start->base < pcimem_start) || + (r_start->base > pcimem_end)) + // Memory range requested is larger than available. + return -1; + + } + return 0; }
@@ -864,12 +901,19 @@ static void pci_bios_map_devices(struct pci_bus *busses) dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end); if (pci_bios_init_root_regions_mem(busses)) { struct pci_region r64_mem, r64_pref; + int i; r64_mem.list.first = NULL; r64_pref.list.first = NULL; - pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM], - &r64_mem); - pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM], - &r64_pref); + + for (i = 0; i <= MaxPCIBus; i++) { + if (busses[i].bus_dev) + continue; + + pci_region_migrate_64bit_entries(&busses[i].r[PCI_REGION_TYPE_MEM], + &r64_mem); + pci_region_migrate_64bit_entries(&busses[i].r[PCI_REGION_TYPE_PREFMEM], + &r64_pref); + }
if (pci_bios_init_root_regions_mem(busses)) panic("PCI: out of 32bit address space\n");