[RFC] xhci: Fix memory leaks caused by halted host.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux