EHCI controller setup needs to occur prior to checking any UHCI or OHCI ports to ensure a high speed device is not mistakenly configured on a full speed "companion" controller. However, only the UHCI/OHCI port scan needs to be delayed, not the full UHCI/OHCI controller init.
This change moves back the ehci controller setup check until port scan in UHCI/OHCI.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/usb-ehci.c | 8 ++++++-- src/hw/usb-ehci.h | 1 + src/hw/usb-ohci.c | 3 +++ src/hw/usb-uhci.c | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c index 41f8579..010746c 100644 --- a/src/hw/usb-ehci.c +++ b/src/hw/usb-ehci.c @@ -337,9 +337,13 @@ ehci_setup(void) if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_EHCI) ehci_controller_setup(pci); } +}
- // Wait for all EHCI controllers to initialize. This forces OHCI/UHCI - // setup to always be after any EHCI ports are routed to EHCI. +// Wait for all EHCI controllers to initialize. This forces OHCI/UHCI +// setup to always be after any EHCI ports are routed to EHCI. +void +ehci_wait_controllers(void) +{ while (PendingEHCI) yield(); } diff --git a/src/hw/usb-ehci.h b/src/hw/usb-ehci.h index 88f7b6a..0442188 100644 --- a/src/hw/usb-ehci.h +++ b/src/hw/usb-ehci.h @@ -3,6 +3,7 @@
// usb-ehci.c void ehci_setup(void); +void ehci_wait_controllers(void); struct usbdevice_s; struct usb_endpoint_descriptor; struct usb_pipe; diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c index 42f8a06..7ed964f 100644 --- a/src/hw/usb-ohci.c +++ b/src/hw/usb-ohci.c @@ -14,6 +14,7 @@ #include "pci_regs.h" // PCI_BASE_ADDRESS_0 #include "string.h" // memset #include "usb.h" // struct usb_s +#include "usb-ehci.h" // ehci_wait_controllers #include "usb-ohci.h" // struct ohci_hcca #include "util.h" // msleep #include "x86.h" // readl @@ -96,6 +97,8 @@ static int check_ohci_ports(struct usb_ohci_s *cntl) { ASSERT32FLAT(); + // Wait for ehci init - in case this is a "companion controller" + ehci_wait_controllers(); // Turn on power for all devices on roothub. u32 rha = readl(&cntl->regs->roothub_a); rha &= ~(RH_A_PSM | RH_A_OCPM); diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c index 69c33ee..6d8aa47 100644 --- a/src/hw/usb-uhci.c +++ b/src/hw/usb-uhci.c @@ -13,6 +13,7 @@ #include "pci_regs.h" // PCI_BASE_ADDRESS_4 #include "string.h" // memset #include "usb.h" // struct usb_s +#include "usb-ehci.h" // ehci_wait_controllers #include "usb-uhci.h" // USBLEGSUP #include "util.h" // msleep #include "x86.h" // outw @@ -94,6 +95,9 @@ static int check_uhci_ports(struct usb_uhci_s *cntl) { ASSERT32FLAT(); + // Wait for ehci init - in case this is a "companion controller" + ehci_wait_controllers(); + struct usbhub_s hub; memset(&hub, 0, sizeof(hub)); hub.cntl = &cntl->usb;
There are no longer any sleep or yield calls during the usb controller device scans, so there is no need to run these device scans in a separate thread.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/usb-ehci.c | 1 - src/hw/usb-ohci.c | 1 - src/hw/usb-uhci.c | 1 - src/hw/usb-xhci.c | 1 - src/hw/usb.c | 16 +++++----------- 5 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c index 010746c..6cc22a5 100644 --- a/src/hw/usb-ehci.c +++ b/src/hw/usb-ehci.c @@ -295,7 +295,6 @@ fail: static void ehci_controller_setup(struct pci_device *pci) { - wait_preempt(); // Avoid pci_config_readl when preempting u16 bdf = pci->bdf; u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); struct ehci_caps *caps = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c index 7ed964f..0c0bf60 100644 --- a/src/hw/usb-ohci.c +++ b/src/hw/usb-ohci.c @@ -277,7 +277,6 @@ ohci_controller_setup(struct pci_device *pci) cntl->usb.pci = pci; cntl->usb.type = USB_TYPE_OHCI;
- wait_preempt(); // Avoid pci_config_readl when preempting u16 bdf = pci->bdf; u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c index 6d8aa47..7a11510 100644 --- a/src/hw/usb-uhci.c +++ b/src/hw/usb-uhci.c @@ -250,7 +250,6 @@ uhci_controller_setup(struct pci_device *pci) warn_noalloc(); return; } - wait_preempt(); // Avoid pci_config_readl when preempting memset(cntl, 0, sizeof(*cntl)); cntl->usb.pci = pci; cntl->usb.type = USB_TYPE_UHCI; diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 089cae7..ad541ab 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -534,7 +534,6 @@ xhci_controller_setup(struct pci_device *pci) } memset(xhci, 0, sizeof(*xhci));
- wait_preempt(); // Avoid pci_config_readl when preempting xhci->baseaddr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) & PCI_BASE_ADDRESS_MEM_MASK; xhci->caps = (void*)(xhci->baseaddr); diff --git a/src/hw/usb.c b/src/hw/usb.c index 2bffd25..20731d1 100644 --- a/src/hw/usb.c +++ b/src/hw/usb.c @@ -485,21 +485,15 @@ usb_enumerate(struct usbhub_s *hub) }
void -__usb_setup(void *data) -{ - dprintf(3, "init usb\n"); - xhci_setup(); - ehci_setup(); - uhci_setup(); - ohci_setup(); -} - -void usb_setup(void) { ASSERT32FLAT(); if (! CONFIG_USB) return; + dprintf(3, "init usb\n"); usb_time_sigatt = romfile_loadint("etc/usb-time-sigatt", USB_TIME_SIGATT); - run_thread(__usb_setup, NULL); + xhci_setup(); + ehci_setup(); + uhci_setup(); + ohci_setup(); }
On Tue, Feb 02, 2016 at 03:03:36PM -0500, Kevin O'Connor wrote:
EHCI controller setup needs to occur prior to checking any UHCI or OHCI ports to ensure a high speed device is not mistakenly configured on a full speed "companion" controller. However, only the UHCI/OHCI port scan needs to be delayed, not the full UHCI/OHCI controller init.
This change moves back the ehci controller setup check until port scan in UHCI/OHCI.
FYI, I committed this series.
-Kevin