diff options
author | Alexey Korolev <alexey.korolev@endace.com> | 2012-04-26 16:51:05 +1200 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2012-04-26 21:52:30 -0400 |
commit | 37c111f253c0cad9601e1bb5beb58df50f49f24f (patch) | |
tree | 008fd55e9fc57bee50695a6216da4c794a402b8d /src | |
parent | ac0cd588edcd63f449b758caf2ff7bef15b4f9f8 (diff) | |
download | seabios-37c111f253c0cad9601e1bb5beb58df50f49f24f.tar.gz |
pciinit: Calculate pci region stats on demand
Do not store pci region stats - instead calulate the
sum and alignment on demand.
Signed-off-by: Alexey Korolev <alexey.korolev@endace.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/pciinit.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/src/pciinit.c b/src/pciinit.c index 0d66dbea..3b801c68 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -40,8 +40,6 @@ struct pci_region_entry { }; struct pci_region { - /* pci region stats */ - u64 sum, align; /* pci region assignments */ u64 base; struct pci_region_entry *list; @@ -369,6 +367,25 @@ static int pci_bios_bridge_region_is64(struct pci_region *r, return 1; } +static u64 pci_region_align(struct pci_region *r) +{ + if (!r->list) + return 1; + // The first entry in the sorted list has the largest alignment + return r->list->align; +} + +static u64 pci_region_sum(struct pci_region *r) +{ + struct pci_region_entry *entry = r->list; + u64 sum = 0; + while (entry) { + sum += entry->size; + entry = entry->next; + } + return sum; +} + static struct pci_region_entry * pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev, int bar, u64 size, u64 align, int type, int is64) @@ -394,10 +411,6 @@ pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev, } entry->next = *pprev; *pprev = entry; - - bus->r[type].sum += size; - if (bus->r[type].align < align) - bus->r[type].align = align; return entry; } @@ -446,9 +459,10 @@ static int pci_bios_check_devices(struct pci_bus *busses) for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) { u64 align = (type == PCI_REGION_TYPE_IO) ? PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN; - if (s->r[type].align > align) - align = s->r[type].align; - u64 size = ALIGN(s->r[type].sum, align); + if (pci_region_align(&s->r[type]) > align) + align = pci_region_align(&s->r[type]); + u64 sum = pci_region_sum(&s->r[type]); + u64 size = ALIGN(sum, align); int is64 = pci_bios_bridge_region_is64(&s->r[type], s->bus_dev, type); // entry->bar is -1 if the entry represents a bridge region @@ -464,26 +478,28 @@ static int pci_bios_check_devices(struct pci_bus *busses) return 0; } -#define ROOT_BASE(top, sum, align) ALIGN_DOWN((top)-(sum),(align) ?: 1) - // Setup region bases (given the regions' size and alignment) static void pci_bios_init_root_regions(struct pci_bus *bus) { - u64 start = BUILD_PCIMEM_START; - u64 end = BUILD_PCIMEM_END; - bus->r[PCI_REGION_TYPE_IO].base = 0xc000; - int reg1 = PCI_REGION_TYPE_PREFMEM, reg2 = PCI_REGION_TYPE_MEM; - if (bus->r[reg1].align < bus->r[reg2].align) { + 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. - reg1 = PCI_REGION_TYPE_MEM; - reg2 = PCI_REGION_TYPE_PREFMEM; + r_end = r_start; + r_start = &bus->r[PCI_REGION_TYPE_PREFMEM]; } - bus->r[reg2].base = ROOT_BASE(end, bus->r[reg2].sum, bus->r[reg2].align); - bus->r[reg1].base = ROOT_BASE(bus->r[reg2].base, bus->r[reg1].sum - , bus->r[reg1].align); - if (bus->r[reg1].base < start) + u64 sum = pci_region_sum(r_end); + u64 align = pci_region_align(r_end); + r_end->base = ALIGN_DOWN((BUILD_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 < BUILD_PCIMEM_START) || + (r_start->base > BUILD_PCIMEM_END)) // Memory range requested is larger than available. panic("PCI: out of address space\n"); } |