Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2517
-gerrit
commit a61b7e41c6cbdf01a8e459e3715520de27d2b720 Author: Gabe Black gabeblack@google.com Date: Thu Nov 8 19:31:23 2012 -0800
libpayload: Handle multifunction bridge devices better.
This change modifies the code in libpayload that scans the PCI hierarchy for USB controllers. Previously, if a devices primary function (function 0) was a bridge, then none of the other functions, if any, would be looked at. If one of the other functions was a bridge, that wouldn't be handled either. The new version looks at each function that's present no matter what, and if it discovers that it's a bridge it scans the other side.
Change-Id: I37f269a4fe505fd32d9594e2daf17ddd78609c15 Signed-off-by: Gabe Black gabeblack@google.com --- payloads/libpayload/drivers/usb/usbinit.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/payloads/libpayload/drivers/usb/usbinit.c b/payloads/libpayload/drivers/usb/usbinit.c index 2e466d3..36cf5e4 100644 --- a/payloads/libpayload/drivers/usb/usbinit.c +++ b/payloads/libpayload/drivers/usb/usbinit.c @@ -126,14 +126,6 @@ static void usb_scan_pci_bus(int bus) if (pci_read_config32(addr, REG_VENDOR_ID) == 0xffff) continue; header_type = pci_read_config8(addr, REG_HEADER_TYPE); - /* If this is a bridge, scan the bus on the other side. */ - if ((header_type & ~HEADER_TYPE_MULTIFUNCTION) == - HEADER_TYPE_BRIDGE) { - int sub_bus = - pci_read_config8(addr, REG_SECONDARY_BUS); - usb_scan_pci_bus(sub_bus); - continue; - } /* * EHCI is defined by standards to be at a higher function * than the USB1 controllers. We don't want to init USB1 + @@ -141,11 +133,22 @@ static void usb_scan_pci_bus(int bus) * comes first. */ /* Check for a multifunction device. */ + int top_func = 0; if (header_type & HEADER_TYPE_MULTIFUNCTION) - for (func = 7; func > 0; func--) + top_func = 7; + for (func = top_func; func >= 0; func--) { + addr = PCI_DEV(bus, dev, func); + header_type = pci_read_config8(addr, REG_HEADER_TYPE); + /* If this is a bridge, scan the other side. */ + if ((header_type & ~HEADER_TYPE_MULTIFUNCTION) == + HEADER_TYPE_BRIDGE) { + int sub_bus = pci_read_config8(addr, + REG_SECONDARY_BUS); + usb_scan_pci_bus(sub_bus); + } else { usb_controller_initialize(bus, dev, func); - /* Initialize function 0. */ - usb_controller_initialize(bus, dev, 0); + } + } } }