aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hcd.c18
-rw-r--r--drivers/usb/core/hub.c15
-rw-r--r--include/linux/usb.h1
3 files changed, 24 insertions, 10 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 0495fa651225..80995ef0868c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1684,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
1684 } 1684 }
1685 } 1685 }
1686 if (cur_alt && new_alt) { 1686 if (cur_alt && new_alt) {
1687 struct usb_interface *iface = usb_ifnum_to_if(udev,
1688 cur_alt->desc.bInterfaceNumber);
1689
1690 if (iface->resetting_device) {
1691 /*
1692 * The USB core just reset the device, so the xHCI host
1693 * and the device will think alt setting 0 is installed.
1694 * However, the USB core will pass in the alternate
1695 * setting installed before the reset as cur_alt. Dig
1696 * out the alternate setting 0 structure, or the first
1697 * alternate setting if a broken device doesn't have alt
1698 * setting 0.
1699 */
1700 cur_alt = usb_altnum_to_altsetting(iface, 0);
1701 if (!cur_alt)
1702 cur_alt = &iface->altsetting[0];
1703 }
1704
1687 /* Drop all the endpoints in the current alt setting */ 1705 /* Drop all the endpoints in the current alt setting */
1688 for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { 1706 for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) {
1689 ret = hcd->driver->drop_endpoint(hcd, udev, 1707 ret = hcd->driver->drop_endpoint(hcd, udev,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b9f5fcd713e2..35cc8b9ba1f5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3695,19 +3695,14 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
3695 usb_enable_interface(udev, intf, true); 3695 usb_enable_interface(udev, intf, true);
3696 ret = 0; 3696 ret = 0;
3697 } else { 3697 } else {
3698 /* We've just reset the device, so it will think alt 3698 /* Let the bandwidth allocation function know that this
3699 * setting 0 is installed. For usb_set_interface() to 3699 * device has been reset, and it will have to use
3700 * work properly, we need to set the current alternate 3700 * alternate setting 0 as the current alternate setting.
3701 * interface setting to 0 (or the first alt setting, if
3702 * the device doesn't have alt setting 0).
3703 */ 3701 */
3704 intf->cur_altsetting = 3702 intf->resetting_device = 1;
3705 usb_find_alt_setting(config, i, 0);
3706 if (!intf->cur_altsetting)
3707 intf->cur_altsetting =
3708 &config->intf_cache[i]->altsetting[0];
3709 ret = usb_set_interface(udev, desc->bInterfaceNumber, 3703 ret = usb_set_interface(udev, desc->bInterfaceNumber,
3710 desc->bAlternateSetting); 3704 desc->bAlternateSetting);
3705 intf->resetting_device = 0;
3711 } 3706 }
3712 if (ret < 0) { 3707 if (ret < 0) {
3713 dev_err(&udev->dev, "failed to restore interface %d " 3708 dev_err(&udev->dev, "failed to restore interface %d "
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e101a2d04d75..d7ace1b80f09 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -192,6 +192,7 @@ struct usb_interface {
192 unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */ 192 unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
193 unsigned needs_binding:1; /* needs delayed unbind/rebind */ 193 unsigned needs_binding:1; /* needs delayed unbind/rebind */
194 unsigned reset_running:1; 194 unsigned reset_running:1;
195 unsigned resetting_device:1; /* true: bandwidth alloc after reset */
195 196
196 struct device dev; /* interface specific device info */ 197 struct device dev; /* interface specific device info */
197 struct device *usb_dev; 198 struct device *usb_dev;