When the xHCI driver is unloaded, the SuperSpeed roothub portion is stopped by the USB core, and xhci_stop() is called for the SS roothub. That function only halts the xHCI host controller. The real cleanup is done when xhci_stop() is later called for the HS roothub. The problem is that if there are HS devices attached to the xHCI controller when the driver is unloaded, the USB core will try to deallocate resources for them, including calling xhci_check_bandwidth() to remove all the endpoints from the host controller device contexts. However, the HS device deallocation happens after the SS roothub is disabled, which means the xHCI host controller is halted. Both xhci_drop_endpoint() and xhci_check_bandwidth() will silently immediately return once they detect the xHCI host is halted. The fix is to move the code to halt the host controller into the HS roothub portion of xhci_stop(). We already had to issue a halt in that code path because xhci_stop() could be called before the USB core had a chance to allocate the SS roothub. So just remove the halting code from the SS code path of xhci_stop(). This patch should be backported to kernels as old as 2.6.39, that contain the commit f6ff0ac878eb420011fa2448851dd48c3a7e7b31 "xhci: Register second xHCI roothub." Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx --- drivers/usb/host/xhci.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 44a4fa6..368111b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -578,21 +578,6 @@ int xhci_run(struct usb_hcd *hcd) return 0; } -static void xhci_only_stop_hcd(struct usb_hcd *hcd) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - - spin_lock_irq(&xhci->lock); - xhci_halt(xhci); - - /* The shared_hcd is going to be deallocated shortly (the USB core only - * calls this function when allocation fails in usb_add_hcd(), or - * usb_remove_hcd() is called). So we need to unset xHCI's pointer. - */ - xhci->shared_hcd = NULL; - spin_unlock_irq(&xhci->lock); -} - /* * Stop xHCI driver. * @@ -607,10 +592,12 @@ void xhci_stop(struct usb_hcd *hcd) u32 temp; struct xhci_hcd *xhci = hcd_to_xhci(hcd); - if (!usb_hcd_is_primary_hcd(hcd)) { - xhci_only_stop_hcd(xhci->shared_hcd); + /* We can't do the reverse of xhci_run and stop the xHCI host controller + * because usb_disable_device may need to deallocate bandwidth for USB + * 2.0 devices. So, do nothing here. + */ + if (!usb_hcd_is_primary_hcd(hcd)) return; - } spin_lock_irq(&xhci->lock); /* Make sure the xHC is halted for a USB3 roothub -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html