On Thu, 2013-12-05 at 18:59 -0500, Kevin O'Connor wrote:
It occurred to me that we could actually simplify the code by initializing all the ehci controllers and then init all the ohci/uhci controllers. The current complex interactions between the PCI walking and EHCI setup is really hard to understand. I put together a sample patch - see attached and at:
That works here, and I think I prefer it to what I'd come up with:
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c index b495d6c..e800322 100644 --- a/src/hw/usb-ehci.c +++ b/src/hw/usb-ehci.c @@ -371,6 +371,9 @@ ehci_setup(struct pci_device *pci, int busid, struct pci_device *comppci) cntl->companion[count++] = comppci; else if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_OHCI) cntl->companion[count++] = comppci; + // Intel Quark quirk. Precisely one OHCI comes *after* the EHCI. + if (comppci->bdf > pci->bdf) + break; comppci = container_of(comppci->node.next, struct pci_device, node); }
diff --git a/src/hw/usb.c b/src/hw/usb.c index 8fe741f..9c09e42 100644 --- a/src/hw/usb.c +++ b/src/hw/usb.c @@ -461,12 +461,28 @@ usb_setup(void) for (;;) { if (pci_classprog(ehcipci) == PCI_CLASS_SERIAL_USB_EHCI) { // Found an ehci controller. + + // Intel Quark got EHCI and OHCI the wrong way round :( + if (pci->vendor == PCI_VENDOR_ID_INTEL && + pci->device == 0x0939) { + struct pci_device *nextpci; + nextpci = container_of_or_null(ehcipci->node.next, + struct pci_device, node); + if (nextpci && nextpci->vendor == PCI_VENDOR_ID_INTEL && + nextpci->device == 0x093a && + pci_bdf_to_busdev(nextpci->bdf) == + pci_bdf_to_busdev(pci->bdf)) { + pci = nextpci; + found++; + } + } int ret = ehci_setup(ehcipci, count++, pci); if (ret) // Error break; count += found; - pci = ehcipci; + if (pci->bdf < ehcipci->bdf) + pci = ehcipci; break; } if (ehcipci->class == PCI_CLASS_SERIAL_USB) @@ -479,6 +495,9 @@ usb_setup(void) break; } } + if (pci->bdf > ehcipci->bdf) + // Quark OHCI. It's been handled. + continue;
if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) uhci_setup(pci, count++);