diff options
author | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2018-06-09 08:25:03 +0300 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2018-06-14 07:59:05 +0000 |
commit | 1dc5ce31ced5baee363f6d30049ca418ce414866 (patch) | |
tree | 7b49e7ceed093073e1c434c77401bb6c0469037f /payloads | |
parent | 3414f6035b5af0ef004742f0ba91fbad266a6162 (diff) | |
download | coreboot-1dc5ce31ced5baee363f6d30049ca418ce414866.tar.xz |
coreinfo: Skip unpopulated PCI functions
Per PCI specification, function 0 must be present,
so functions 1 to 7 can be skipped in this case.
For a device that is not multi-function, it may not
decode function number in the hardware at all. To
avoid registering such a device eight times, skip
scanning functions 1 to 7.
Without the latter fix, a single-function PCI bridge
may call pci_scan_bus() second time and secondary
side devices would get appended second time in the
array devices[]. At that point, quicksort() apparently
hits an infinite recursion loop.
Since pci_scan_bus() is called in part of the early
modules->init() sequence early in main(), the errors
here left coreinfo payload completely silent when
PCI module was built-in on affected system.
Terminal screen was cleared, though.
Change-Id: Ifc6622f050b98afb7196de0cc3a863c4cdfa6c94
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/26990
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'payloads')
-rw-r--r-- | payloads/coreinfo/pci_module.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/payloads/coreinfo/pci_module.c b/payloads/coreinfo/pci_module.c index f79d543d5e..9f10b12703 100644 --- a/payloads/coreinfo/pci_module.c +++ b/payloads/coreinfo/pci_module.c @@ -183,8 +183,14 @@ static void pci_scan_bus(int bus) /* Nobody home. */ if (val == 0xffffffff || val == 0x00000000 || - val == 0x0000ffff || val == 0xffff0000) + val == 0x0000ffff || val == 0xffff0000) { + + /* If function 0 is not present, no need + * to test other functions. */ + if (func == 0) + func = 8; continue; + } /* FIXME: Remove this arbitrary limitation. */ if (devices_index >= MAX_PCI_DEVICES) @@ -197,7 +203,11 @@ static void pci_scan_bus(int bus) /* If this is a bridge, then follow it. */ hdr = pci_read_config8(dev, REG_HEADER_TYPE); - hdr &= 0x7f; + + if ((func == 0) && !(hdr & HEADER_TYPE_MULTIFUNCTION)) + func = 8; + + hdr &= ~HEADER_TYPE_MULTIFUNCTION; if (hdr == HEADER_TYPE_BRIDGE || hdr == HEADER_TYPE_CARDBUS) { unsigned int busses; |