On Tue, Apr 24, 2012 at 06:25:39PM +1200, Alexey Korolev wrote:
Migrate 64bit entries to 64bit pci regions if they do not fit in 32bit range.
[...]
+static void pci_region_migrate_64bit_entries(struct pci_region *from,
struct pci_region *to)
+{
- struct pci_region_entry **pprev = &from->list;
- struct pci_region_entry **last = &to->list;
- while(*pprev) {
if ((*pprev)->is64) {
struct pci_region_entry *entry;
entry = *pprev;
/* Delete the entry and move next */
*pprev = (*pprev)->next;
/* Add entry at tail to keep a sorted order */
entry->next = NULL;
if (*last) {
(*last)->next = entry;
last = &(*last)->next;
}
else
(*last) = entry;
}
else
pprev = &(*pprev)->next;
- }
+}
It should be possible to simplify this - something like (untested):
static void pci_region_migrate_64bit_entries(struct pci_region *from, struct pci_region *to) { struct pci_region_entry **pprev = &from->list, **last = &to->list; for (; *pprev; pprev = &(*pprev)->next) { struct pci_region_entry *entry = *pprev; if (!entry->is64) continue; // Move from source list to dest list. *pprev = entry->next; entry->next = NULL; *last = entry; last = &entry->next; } }
[...]
static void pci_bios_map_devices(struct pci_bus *busses) {
- if (pci_bios_init_root_regions(busses)) {
struct pci_region r64_mem, r64_pref;
r64_mem.list = NULL;
r64_pref.list = 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);
if (pci_bios_init_root_regions(busses))
panic("PCI: out of address space\n");
r64_mem.base = BUILD_PCIMEM64_START;
r64_pref.base = ALIGN(r64_mem.base + pci_region_sum(&r64_mem),
pci_region_align(&r64_pref));
There should be a check to see if the regions fit. Maybe pass start/end into pci_bios_init_root_regions() and call it again for the
4g region?
pci_region_map_entries(busses, &r64_mem);
pci_region_map_entries(busses, &r64_pref);
- } // Map regions on each device.
This doesn't look right to me. This will map the devices on bus 0 to the proper >4g address, but devices on any subsequent bus will use busses[0].r[].base which will be reset to the <4gig address. Perhaps pull base out of pci_region and make pci_region_map_entries() recursive?
-Kevin