diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hub.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 15 |
2 files changed, 17 insertions, 1 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90ae1753dda1..ca339bc799e4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1634,6 +1634,7 @@ void usb_disconnect(struct usb_device **pdev) | |||
1634 | { | 1634 | { |
1635 | struct usb_device *udev = *pdev; | 1635 | struct usb_device *udev = *pdev; |
1636 | int i; | 1636 | int i; |
1637 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
1637 | 1638 | ||
1638 | if (!udev) { | 1639 | if (!udev) { |
1639 | pr_debug ("%s nodev\n", __func__); | 1640 | pr_debug ("%s nodev\n", __func__); |
@@ -1661,7 +1662,9 @@ void usb_disconnect(struct usb_device **pdev) | |||
1661 | * so that the hardware is now fully quiesced. | 1662 | * so that the hardware is now fully quiesced. |
1662 | */ | 1663 | */ |
1663 | dev_dbg (&udev->dev, "unregistering device\n"); | 1664 | dev_dbg (&udev->dev, "unregistering device\n"); |
1665 | mutex_lock(hcd->bandwidth_mutex); | ||
1664 | usb_disable_device(udev, 0); | 1666 | usb_disable_device(udev, 0); |
1667 | mutex_unlock(hcd->bandwidth_mutex); | ||
1665 | usb_hcd_synchronize_unlinks(udev); | 1668 | usb_hcd_synchronize_unlinks(udev); |
1666 | 1669 | ||
1667 | usb_remove_ep_devs(&udev->ep0); | 1670 | usb_remove_ep_devs(&udev->ep0); |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 5701e857392b..64c7ab4702df 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1135,10 +1135,13 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, | |||
1135 | * Deallocates hcd/hardware state for the endpoints (nuking all or most | 1135 | * Deallocates hcd/hardware state for the endpoints (nuking all or most |
1136 | * pending urbs) and usbcore state for the interfaces, so that usbcore | 1136 | * pending urbs) and usbcore state for the interfaces, so that usbcore |
1137 | * must usb_set_configuration() before any interfaces could be used. | 1137 | * must usb_set_configuration() before any interfaces could be used. |
1138 | * | ||
1139 | * Must be called with hcd->bandwidth_mutex held. | ||
1138 | */ | 1140 | */ |
1139 | void usb_disable_device(struct usb_device *dev, int skip_ep0) | 1141 | void usb_disable_device(struct usb_device *dev, int skip_ep0) |
1140 | { | 1142 | { |
1141 | int i; | 1143 | int i; |
1144 | struct usb_hcd *hcd = bus_to_hcd(dev->bus); | ||
1142 | 1145 | ||
1143 | /* getting rid of interfaces will disconnect | 1146 | /* getting rid of interfaces will disconnect |
1144 | * any drivers bound to them (a key side effect) | 1147 | * any drivers bound to them (a key side effect) |
@@ -1172,6 +1175,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1172 | 1175 | ||
1173 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, | 1176 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, |
1174 | skip_ep0 ? "non-ep0" : "all"); | 1177 | skip_ep0 ? "non-ep0" : "all"); |
1178 | if (hcd->driver->check_bandwidth) { | ||
1179 | /* First pass: Cancel URBs, leave endpoint pointers intact. */ | ||
1180 | for (i = skip_ep0; i < 16; ++i) { | ||
1181 | usb_disable_endpoint(dev, i, false); | ||
1182 | usb_disable_endpoint(dev, i + USB_DIR_IN, false); | ||
1183 | } | ||
1184 | /* Remove endpoints from the host controller internal state */ | ||
1185 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); | ||
1186 | /* Second pass: remove endpoint pointers */ | ||
1187 | } | ||
1175 | for (i = skip_ep0; i < 16; ++i) { | 1188 | for (i = skip_ep0; i < 16; ++i) { |
1176 | usb_disable_endpoint(dev, i, true); | 1189 | usb_disable_endpoint(dev, i, true); |
1177 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); | 1190 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
@@ -1727,6 +1740,7 @@ free_interfaces: | |||
1727 | /* if it's already configured, clear out old state first. | 1740 | /* if it's already configured, clear out old state first. |
1728 | * getting rid of old interfaces means unbinding their drivers. | 1741 | * getting rid of old interfaces means unbinding their drivers. |
1729 | */ | 1742 | */ |
1743 | mutex_lock(hcd->bandwidth_mutex); | ||
1730 | if (dev->state != USB_STATE_ADDRESS) | 1744 | if (dev->state != USB_STATE_ADDRESS) |
1731 | usb_disable_device(dev, 1); /* Skip ep0 */ | 1745 | usb_disable_device(dev, 1); /* Skip ep0 */ |
1732 | 1746 | ||
@@ -1739,7 +1753,6 @@ free_interfaces: | |||
1739 | * host controller will not allow submissions to dropped endpoints. If | 1753 | * host controller will not allow submissions to dropped endpoints. If |
1740 | * this call fails, the device state is unchanged. | 1754 | * this call fails, the device state is unchanged. |
1741 | */ | 1755 | */ |
1742 | mutex_lock(hcd->bandwidth_mutex); | ||
1743 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); | 1756 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); |
1744 | if (ret < 0) { | 1757 | if (ret < 0) { |
1745 | mutex_unlock(hcd->bandwidth_mutex); | 1758 | mutex_unlock(hcd->bandwidth_mutex); |