The patch changes the bridge ressource allocation: Unused memory windows are disabled: If none of the devices connected to the bridge has -- say -- I/O bars, then the I/O memory window is turned off. This implies that bridges without devices don't get any ressources assigned. The pci bridge spec wants us behave that way (figured while looking at drivers/pci/setup-bus.c in the linux kernel source tree).
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/pciinit.c | 43 +++++++++++++++++++++++++++++++++---------- 1 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index 33b9bf7..a03e17c 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -457,6 +457,8 @@ static void pci_bios_check_devices(struct pci_bus *busses) for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { u64 limit = (type == PCI_REGION_TYPE_IO) ? PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN; + if (s->r[type].sum == 0) + continue; s->r[type].size = s->r[type].sum; if (s->r[type].size < limit) s->r[type].size = limit; @@ -505,6 +507,8 @@ static void pci_bios_init_bus_bases(struct pci_bus *bus) int type, i;
for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { + if (bus->r[type].sum == 0) + continue; dprintf(1, " type %s max %llx sum %llx base %llx\n", region_type_name[type], bus->r[type].max, bus->r[type].sum, bus->r[type].base); @@ -522,9 +526,10 @@ static void pci_bios_init_bus_bases(struct pci_bus *bus) } }
-static u32 pci_bios_bus_get_addr(struct pci_bus *bus, int type, u32 size) +static u64 pci_bios_bus_get_addr(struct pci_bus *bus, int type, u64 size) { - u32 index, addr; + u32 index; + u64 addr;
index = pci_size_to_index(size, type); addr = bus->r[type].bases[index]; @@ -552,30 +557,48 @@ static void pci_bios_map_devices(struct pci_bus *busses) struct pci_bus *parent = &busses[pci_bdf_to_bus(bdf)]; int type; for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { + if (s->r[type].sum == 0) + continue; s->r[type].base = pci_bios_bus_get_addr( parent, type, s->r[type].size); } dprintf(1, "PCI: init bases bus %d (secondary)\n", secondary_bus); pci_bios_init_bus_bases(s);
- u64 base = s->r[PCI_REGION_TYPE_IO].base; - u64 limit = base + s->r[PCI_REGION_TYPE_IO].size - 1; + u64 base, limit; + if (s->r[PCI_REGION_TYPE_IO].sum) { + base = s->r[PCI_REGION_TYPE_IO].base; + limit = base + s->r[PCI_REGION_TYPE_IO].size - 1; + } else { + base = PCI_BRIDGE_IO_MIN; + limit = 0; + } pci_config_writeb(bdf, PCI_IO_BASE, base >> PCI_IO_SHIFT); pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0); pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT); pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
- base = s->r[PCI_REGION_TYPE_MEM].base; - limit = base + s->r[PCI_REGION_TYPE_MEM].size - 1; + if (s->r[PCI_REGION_TYPE_MEM].sum) { + base = s->r[PCI_REGION_TYPE_MEM].base; + limit = base + s->r[PCI_REGION_TYPE_MEM].size - 1; + } else { + base = PCI_BRIDGE_MEM_MIN; + limit = 0; + } pci_config_writew(bdf, PCI_MEMORY_BASE, base >> PCI_MEMORY_SHIFT); pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
- base = s->r[PCI_REGION_TYPE_PREFMEM].base; - limit = base + s->r[PCI_REGION_TYPE_PREFMEM].size - 1; + if (s->r[PCI_REGION_TYPE_PREFMEM].sum) { + base = s->r[PCI_REGION_TYPE_PREFMEM].base; + limit = base + s->r[PCI_REGION_TYPE_PREFMEM].size - 1; + } else { + base = PCI_BRIDGE_MEM_MIN; + limit = 0; + } pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, base >> PCI_PREF_MEMORY_SHIFT); pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT); - pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0); - pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0); + pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, base >> 32); + pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, base >> 32); }
// Map regions on each device.