summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2015-03-15 23:24:32 +0300
committerFelipe Balbi <balbi@ti.com>2015-03-19 19:22:57 +0300
commit7252f1bfd4bc97ec4b5fa7adaf3a1a45c325635c (patch)
tree04c39ed0e16ed67741597bab709256724b5ded45 /drivers/usb/dwc2
parent46f5cace1cd0559c335dfd4a5b8f57456d1bd6a1 (diff)
downloadlinux-7252f1bfd4bc97ec4b5fa7adaf3a1a45c325635c.tar.xz
usb: dwc2: avoid leaking DMA channels on disconnection
When the HCD is disconnected, the DMA transfers still in-flight were cleaned-up but the count of available DMA channels (e.g. available_host_channels) was not reset. The pool of DMA channels can be depleted when doing unclean disconnection of USB peripherals, and reaches the point where no transfer was possible until the next reboot/reload of the driver. Tested by putting a programmable USB mux on the port and randomly plugging/unpluging a USB HUB with USB mass-storage key, USB-audio and USB-ethernet dongle connected to its downstream ports, and also doing the disconnection early while the devices are still enumerating to get more URBs in-flight. After the patch, the devices are still enumerating after thousands of cycles, while the port was totally dead before. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r--drivers/usb/dwc2/hcd.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index c78c8740db1d..559b55e5debb 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -257,6 +257,14 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
*/
channel->qh = NULL;
}
+ /* All channels have been freed, mark them available */
+ if (hsotg->core_params->uframe_sched > 0) {
+ hsotg->available_host_channels =
+ hsotg->core_params->host_channels;
+ } else {
+ hsotg->non_periodic_channels = 0;
+ hsotg->periodic_channels = 0;
+ }
}
/**