aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-12 21:06:37 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-16 20:59:22 -0400
commit834cb0fc4712a3b21c6b8c5cb55bd13607191311 (patch)
treeaa76f94996fbe80d19e2b278545c39143b889e0b /drivers/usb
parent30f89ca021c3e584b61bc5a14eede89f74b2e826 (diff)
xhci: Fix memory leak bug when dropping endpoints
When the USB core wants to change to an alternate interface setting that doesn't include an active endpoint, or de-configuring the device, the xHCI driver needs to issue a Configure Endpoint command to tell the host to drop some endpoints from the schedule. After the command completes, the xHCI driver needs to free rings for any endpoints that were dropped. Unfortunately, the xHCI driver wasn't actually freeing the endpoint rings for dropped endpoints. The rings would be freed if the endpoint's information was simply changed (and a new ring was installed), but dropped endpoints never had their rings freed. This caused errors when the ring segment DMA pool was freed when the xHCI driver was unloaded: [ 5582.883995] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff88003371d000 busy [ 5582.884002] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff880033716000 busy [ 5582.884011] xhci_hcd 0000:06:00.0: dma_pool_destroy xHCI ring segments, ffff880033455000 busy [ 5582.884018] xhci_hcd 0000:06:00.0: Freed segment pool [ 5582.884026] xhci_hcd 0000:06:00.0: Freed device context pool [ 5582.884033] xhci_hcd 0000:06:00.0: Freed small stream array pool [ 5582.884038] xhci_hcd 0000:06:00.0: Freed medium stream array pool [ 5582.884048] xhci_hcd 0000:06:00.0: xhci_stop completed - status = 1 [ 5582.884061] xhci_hcd 0000:06:00.0: USB bus 3 deregistered [ 5582.884193] xhci_hcd 0000:06:00.0: PCI INT A disabled Fix this issue and free endpoint rings when their endpoints are successfully dropped. This patch should be backported to kernels as old as 2.6.31. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@kernel.org
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 013e113b818a..8f2a56ece44f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1701,8 +1701,17 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
1701 xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1701 xhci_dbg_ctx(xhci, virt_dev->out_ctx,
1702 LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info))); 1702 LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
1703 1703
1704 /* Free any rings that were dropped, but not changed. */
1705 for (i = 1; i < 31; ++i) {
1706 if ((ctrl_ctx->drop_flags & (1 << (i + 1))) &&
1707 !(ctrl_ctx->add_flags & (1 << (i + 1))))
1708 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
1709 }
1704 xhci_zero_in_ctx(xhci, virt_dev); 1710 xhci_zero_in_ctx(xhci, virt_dev);
1705 /* Install new rings and free or cache any old rings */ 1711 /*
1712 * Install any rings for completely new endpoints or changed endpoints,
1713 * and free or cache any old rings from changed endpoints.
1714 */
1706 for (i = 1; i < 31; ++i) { 1715 for (i = 1; i < 31; ++i) {
1707 if (!virt_dev->eps[i].new_ring) 1716 if (!virt_dev->eps[i].new_ring)
1708 continue; 1717 continue;