[SeaBIOS] [PATCH 11/12] Migrate 64bit entries to 64bit pci regions
Alexey Korolev
alexey.korolev at endace.com
Wed Apr 25 08:25:07 CEST 2012
On 25/04/12 13:48, Kevin O'Connor wrote:
> 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;
> }
> }
Sorry it's not working.
I agree it's possible to simplify code a bit.
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 the order */
entry->next = NULL;
*last = entry;
last = &entry->next;
}
else
pprev = &(*pprev)->next;
}
}
That should work.
> [...]
>> 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?
Agree, I just ignored the check as 64bit range size is 2^39.
I will think how to make it better.
>> + 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?
No recursion is need here!
We map all entries which are 64bit on root bus.
If entry is a bridge region - a corresponding bus address will be updated.
Region won't be reseted to <4gig address as address is derived from parent region only.
Thanks,
Alexey
More information about the SeaBIOS
mailing list