aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@vmware.com>2011-04-13 02:06:28 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-04-13 19:57:31 -0400
commit2dea75d96ade3c7cd2bfe73f99c7b3291dc3d03a (patch)
tree5c96640b0f28191b536d918fa870926dc053b1c8 /drivers/usb
parent386139d7c8f22d4983ca89de35d339cc41bb0996 (diff)
USB: xhci - also free streams when resetting devices
Currently, when resetting a device, xHCI driver disables all but one endpoints and frees their rings, but leaves alone any streams that might have been allocated. Later, when users try to free allocated streams, we oops in xhci_setup_no_streams_ep_input_ctx() because ep->ring is NULL. Let's free not only rings but also stream data as well, so that calling free_streams() on a device that was reset will be safe. This should be queued for stable trees back to 2.6.35. Reviewed-by: Micah Elizabeth Scott <micah@vmware.com> Signed-off-by: Dmitry Torokhov <dtor@vmware.com> 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.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 196e0181b2e..48706c0d657 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2386,10 +2386,18 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
2386 /* Everything but endpoint 0 is disabled, so free or cache the rings. */ 2386 /* Everything but endpoint 0 is disabled, so free or cache the rings. */
2387 last_freed_endpoint = 1; 2387 last_freed_endpoint = 1;
2388 for (i = 1; i < 31; ++i) { 2388 for (i = 1; i < 31; ++i) {
2389 if (!virt_dev->eps[i].ring) 2389 struct xhci_virt_ep *ep = &virt_dev->eps[i];
2390 continue; 2390
2391 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); 2391 if (ep->ep_state & EP_HAS_STREAMS) {
2392 last_freed_endpoint = i; 2392 xhci_free_stream_info(xhci, ep->stream_info);
2393 ep->stream_info = NULL;
2394 ep->ep_state &= ~EP_HAS_STREAMS;
2395 }
2396
2397 if (ep->ring) {
2398 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
2399 last_freed_endpoint = i;
2400 }
2393 } 2401 }
2394 xhci_dbg(xhci, "Output context after successful reset device cmd:\n"); 2402 xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
2395 xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint); 2403 xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);