From 7a7b562d08ad6db98d6c8ec634620a11aaf8921a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 8 Nov 2013 16:37:26 +0100 Subject: [PATCH] usb: Clear host_endpoint->streams when implicitly freeing streams If streams are still allocated on device-reset or set-interface then the hcd code implictly frees the streams. Clear host_endpoint->streams in this case so that if a driver later tries to re-allocate them it won't run afoul of the device already having streams check in usb_alloc_streams(). Note normally streams still being allocated at reset / set-intf would be a driver bug, but this can happen without it being a driver bug on reset-resume. Signed-off-by: Hans de Goede Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 5 ++++- drivers/usb/core/message.c | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 763c3134dd78..4f7629d1ba6a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5131,7 +5131,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_device_descriptor descriptor = udev->descriptor; struct usb_host_bos *bos; - int i, ret = 0; + int i, j, ret = 0; int port1 = udev->portnum; if (udev->state == USB_STATE_NOTATTACHED || @@ -5257,6 +5257,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev) ret); goto re_enumerate; } + /* Resetting also frees any allocated streams */ + for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++) + intf->cur_altsetting->endpoint[j].streams = 0; } done: diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f829a1aad1c3..964695741031 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1293,8 +1293,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) struct usb_interface *iface; struct usb_host_interface *alt; struct usb_hcd *hcd = bus_to_hcd(dev->bus); - int ret; - int manual = 0; + int i, ret, manual = 0; unsigned int epaddr; unsigned int pipe; @@ -1329,6 +1328,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) mutex_unlock(hcd->bandwidth_mutex); return -ENOMEM; } + /* Changing alt-setting also frees any allocated streams */ + for (i = 0; i < iface->cur_altsetting->desc.bNumEndpoints; i++) + iface->cur_altsetting->endpoint[i].streams = 0; + ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt); if (ret < 0) { dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",