aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-10-09 11:19:26 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2014-03-04 18:38:03 -0500
commit6343e8bf09de16ab4dcae2c6ca1a0e8dbd4dd770 (patch)
treead0ffaaeee9723f382a12220d87152582d241a59 /drivers/usb/core/driver.c
parent8d4f70b2fa52ca80f74faebc2471f74ee374cf61 (diff)
usb-core: Free bulk streams on interface release
Documentation/usb/bulk-streams.txt says: All stream IDs will be deallocated when the driver releases the interface, to ensure that drivers that don't support streams will be able to use the endpoint This commit actually implements this. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 85e0450a2bc7..08283d40616c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -400,8 +400,9 @@ static int usb_unbind_interface(struct device *dev)
400{ 400{
401 struct usb_driver *driver = to_usb_driver(dev->driver); 401 struct usb_driver *driver = to_usb_driver(dev->driver);
402 struct usb_interface *intf = to_usb_interface(dev); 402 struct usb_interface *intf = to_usb_interface(dev);
403 struct usb_host_endpoint *ep, **eps = NULL;
403 struct usb_device *udev; 404 struct usb_device *udev;
404 int error, r, lpm_disable_error; 405 int i, j, error, r, lpm_disable_error;
405 406
406 intf->condition = USB_INTERFACE_UNBINDING; 407 intf->condition = USB_INTERFACE_UNBINDING;
407 408
@@ -425,6 +426,26 @@ static int usb_unbind_interface(struct device *dev)
425 driver->disconnect(intf); 426 driver->disconnect(intf);
426 usb_cancel_queued_reset(intf); 427 usb_cancel_queued_reset(intf);
427 428
429 /* Free streams */
430 for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
431 ep = &intf->cur_altsetting->endpoint[i];
432 if (ep->streams == 0)
433 continue;
434 if (j == 0) {
435 eps = kmalloc(USB_MAXENDPOINTS * sizeof(void *),
436 GFP_KERNEL);
437 if (!eps) {
438 dev_warn(dev, "oom, leaking streams\n");
439 break;
440 }
441 }
442 eps[j++] = ep;
443 }
444 if (j) {
445 usb_free_streams(intf, eps, j, GFP_KERNEL);
446 kfree(eps);
447 }
448
428 /* Reset other interface state. 449 /* Reset other interface state.
429 * We cannot do a Set-Interface if the device is suspended or 450 * We cannot do a Set-Interface if the device is suspended or
430 * if it is prepared for a system sleep (since installing a new 451 * if it is prepared for a system sleep (since installing a new