aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 6dac3b802d4..80995ef0868 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1597,7 +1597,9 @@ rescan:
}
/**
- * Check whether a new bandwidth setting exceeds the bus bandwidth.
+ * usb_hcd_alloc_bandwidth - check whether a new bandwidth setting exceeds
+ * the bus bandwidth
+ * @udev: target &usb_device
* @new_config: new configuration to install
* @cur_alt: the current alternate interface setting
* @new_alt: alternate interface setting that is being installed
@@ -1682,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
}
}
if (cur_alt && new_alt) {
+ struct usb_interface *iface = usb_ifnum_to_if(udev,
+ cur_alt->desc.bInterfaceNumber);
+
+ if (iface->resetting_device) {
+ /*
+ * The USB core just reset the device, so the xHCI host
+ * and the device will think alt setting 0 is installed.
+ * However, the USB core will pass in the alternate
+ * setting installed before the reset as cur_alt. Dig
+ * out the alternate setting 0 structure, or the first
+ * alternate setting if a broken device doesn't have alt
+ * setting 0.
+ */
+ cur_alt = usb_altnum_to_altsetting(iface, 0);
+ if (!cur_alt)
+ cur_alt = &iface->altsetting[0];
+ }
+
/* Drop all the endpoints in the current alt setting */
for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) {
ret = hcd->driver->drop_endpoint(hcd, udev,