diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-07-15 22:11:34 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-07-15 22:11:34 -0400 |
commit | 8c11642a50555e584774737f7c296f9aece310cf (patch) | |
tree | 1ff8dfaf05479593ef2c50378a68dfc6aec495a5 /drivers/usb/core | |
parent | 5d10302f46df1d9a85c34ea97f9b6c29e414482e (diff) | |
parent | 620917de59eeb934b9f8cf35cc2d95c1ac8ed0fc (diff) |
Merge commit 'v3.0-rc7' into devicetree/next
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/driver.c | 17 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 16 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 26 |
3 files changed, 48 insertions, 11 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e35a17687c05..34e3da5aa72a 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev) | |||
375 | * Just re-enable it without affecting the endpoint toggles. | 375 | * Just re-enable it without affecting the endpoint toggles. |
376 | */ | 376 | */ |
377 | usb_enable_interface(udev, intf, false); | 377 | usb_enable_interface(udev, intf, false); |
378 | } else if (!error && !intf->dev.power.in_suspend) { | 378 | } else if (!error && !intf->dev.power.is_prepared) { |
379 | r = usb_set_interface(udev, intf->altsetting[0]. | 379 | r = usb_set_interface(udev, intf->altsetting[0]. |
380 | desc.bInterfaceNumber, 0); | 380 | desc.bInterfaceNumber, 0); |
381 | if (r < 0) | 381 | if (r < 0) |
@@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf) | |||
960 | } | 960 | } |
961 | 961 | ||
962 | /* Try to rebind the interface */ | 962 | /* Try to rebind the interface */ |
963 | if (!intf->dev.power.in_suspend) { | 963 | if (!intf->dev.power.is_prepared) { |
964 | intf->needs_binding = 0; | 964 | intf->needs_binding = 0; |
965 | rc = device_attach(&intf->dev); | 965 | rc = device_attach(&intf->dev); |
966 | if (rc < 0) | 966 | if (rc < 0) |
@@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev, | |||
1107 | if (intf->condition == USB_INTERFACE_UNBOUND) { | 1107 | if (intf->condition == USB_INTERFACE_UNBOUND) { |
1108 | 1108 | ||
1109 | /* Carry out a deferred switch to altsetting 0 */ | 1109 | /* Carry out a deferred switch to altsetting 0 */ |
1110 | if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) { | 1110 | if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) { |
1111 | usb_set_interface(udev, intf->altsetting[0]. | 1111 | usb_set_interface(udev, intf->altsetting[0]. |
1112 | desc.bInterfaceNumber, 0); | 1112 | desc.bInterfaceNumber, 0); |
1113 | intf->needs_altsetting0 = 0; | 1113 | intf->needs_altsetting0 = 0; |
@@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1187 | for (i = n - 1; i >= 0; --i) { | 1187 | for (i = n - 1; i >= 0; --i) { |
1188 | intf = udev->actconfig->interface[i]; | 1188 | intf = udev->actconfig->interface[i]; |
1189 | status = usb_suspend_interface(udev, intf, msg); | 1189 | status = usb_suspend_interface(udev, intf, msg); |
1190 | |||
1191 | /* Ignore errors during system sleep transitions */ | ||
1192 | if (!(msg.event & PM_EVENT_AUTO)) | ||
1193 | status = 0; | ||
1190 | if (status != 0) | 1194 | if (status != 0) |
1191 | break; | 1195 | break; |
1192 | } | 1196 | } |
1193 | } | 1197 | } |
1194 | if (status == 0) | 1198 | if (status == 0) { |
1195 | status = usb_suspend_device(udev, msg); | 1199 | status = usb_suspend_device(udev, msg); |
1196 | 1200 | ||
1201 | /* Again, ignore errors during system sleep transitions */ | ||
1202 | if (!(msg.event & PM_EVENT_AUTO)) | ||
1203 | status = 0; | ||
1204 | } | ||
1205 | |||
1197 | /* If the suspend failed, resume interfaces that did get suspended */ | 1206 | /* If the suspend failed, resume interfaces that did get suspended */ |
1198 | if (status != 0) { | 1207 | if (status != 0) { |
1199 | msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); | 1208 | msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90ae1753dda1..a428aa080a36 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); |
@@ -2362,6 +2365,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2362 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2365 | USB_DEVICE_REMOTE_WAKEUP, 0, |
2363 | NULL, 0, | 2366 | NULL, 0, |
2364 | USB_CTRL_SET_TIMEOUT); | 2367 | USB_CTRL_SET_TIMEOUT); |
2368 | |||
2369 | /* System sleep transitions should never fail */ | ||
2370 | if (!(msg.event & PM_EVENT_AUTO)) | ||
2371 | status = 0; | ||
2365 | } else { | 2372 | } else { |
2366 | /* device has up to 10 msec to fully suspend */ | 2373 | /* device has up to 10 msec to fully suspend */ |
2367 | dev_dbg(&udev->dev, "usb %ssuspend\n", | 2374 | dev_dbg(&udev->dev, "usb %ssuspend\n", |
@@ -2611,16 +2618,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2611 | struct usb_device *hdev = hub->hdev; | 2618 | struct usb_device *hdev = hub->hdev; |
2612 | unsigned port1; | 2619 | unsigned port1; |
2613 | 2620 | ||
2614 | /* fail if children aren't already suspended */ | 2621 | /* Warn if children aren't already suspended */ |
2615 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 2622 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
2616 | struct usb_device *udev; | 2623 | struct usb_device *udev; |
2617 | 2624 | ||
2618 | udev = hdev->children [port1-1]; | 2625 | udev = hdev->children [port1-1]; |
2619 | if (udev && udev->can_submit) { | 2626 | if (udev && udev->can_submit) { |
2620 | if (!(msg.event & PM_EVENT_AUTO)) | 2627 | dev_warn(&intf->dev, "port %d nyet suspended\n", port1); |
2621 | dev_dbg(&intf->dev, "port %d nyet suspended\n", | 2628 | if (msg.event & PM_EVENT_AUTO) |
2622 | port1); | 2629 | return -EBUSY; |
2623 | return -EBUSY; | ||
2624 | } | 2630 | } |
2625 | } | 2631 | } |
2626 | 2632 | ||
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 5701e857392b..0b5ec234c787 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1135,15 +1135,26 @@ 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) |
1145 | */ | 1148 | */ |
1146 | if (dev->actconfig) { | 1149 | if (dev->actconfig) { |
1150 | /* | ||
1151 | * FIXME: In order to avoid self-deadlock involving the | ||
1152 | * bandwidth_mutex, we have to mark all the interfaces | ||
1153 | * before unregistering any of them. | ||
1154 | */ | ||
1155 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) | ||
1156 | dev->actconfig->interface[i]->unregistering = 1; | ||
1157 | |||
1147 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { | 1158 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { |
1148 | struct usb_interface *interface; | 1159 | struct usb_interface *interface; |
1149 | 1160 | ||
@@ -1153,7 +1164,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1153 | continue; | 1164 | continue; |
1154 | dev_dbg(&dev->dev, "unregistering interface %s\n", | 1165 | dev_dbg(&dev->dev, "unregistering interface %s\n", |
1155 | dev_name(&interface->dev)); | 1166 | dev_name(&interface->dev)); |
1156 | interface->unregistering = 1; | ||
1157 | remove_intf_ep_devs(interface); | 1167 | remove_intf_ep_devs(interface); |
1158 | device_del(&interface->dev); | 1168 | device_del(&interface->dev); |
1159 | } | 1169 | } |
@@ -1172,6 +1182,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1172 | 1182 | ||
1173 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, | 1183 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, |
1174 | skip_ep0 ? "non-ep0" : "all"); | 1184 | skip_ep0 ? "non-ep0" : "all"); |
1185 | if (hcd->driver->check_bandwidth) { | ||
1186 | /* First pass: Cancel URBs, leave endpoint pointers intact. */ | ||
1187 | for (i = skip_ep0; i < 16; ++i) { | ||
1188 | usb_disable_endpoint(dev, i, false); | ||
1189 | usb_disable_endpoint(dev, i + USB_DIR_IN, false); | ||
1190 | } | ||
1191 | /* Remove endpoints from the host controller internal state */ | ||
1192 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); | ||
1193 | /* Second pass: remove endpoint pointers */ | ||
1194 | } | ||
1175 | for (i = skip_ep0; i < 16; ++i) { | 1195 | for (i = skip_ep0; i < 16; ++i) { |
1176 | usb_disable_endpoint(dev, i, true); | 1196 | usb_disable_endpoint(dev, i, true); |
1177 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); | 1197 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
@@ -1273,6 +1293,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1273 | interface); | 1293 | interface); |
1274 | return -EINVAL; | 1294 | return -EINVAL; |
1275 | } | 1295 | } |
1296 | if (iface->unregistering) | ||
1297 | return -ENODEV; | ||
1276 | 1298 | ||
1277 | alt = usb_altnum_to_altsetting(iface, alternate); | 1299 | alt = usb_altnum_to_altsetting(iface, alternate); |
1278 | if (!alt) { | 1300 | if (!alt) { |
@@ -1727,6 +1749,7 @@ free_interfaces: | |||
1727 | /* if it's already configured, clear out old state first. | 1749 | /* if it's already configured, clear out old state first. |
1728 | * getting rid of old interfaces means unbinding their drivers. | 1750 | * getting rid of old interfaces means unbinding their drivers. |
1729 | */ | 1751 | */ |
1752 | mutex_lock(hcd->bandwidth_mutex); | ||
1730 | if (dev->state != USB_STATE_ADDRESS) | 1753 | if (dev->state != USB_STATE_ADDRESS) |
1731 | usb_disable_device(dev, 1); /* Skip ep0 */ | 1754 | usb_disable_device(dev, 1); /* Skip ep0 */ |
1732 | 1755 | ||
@@ -1739,7 +1762,6 @@ free_interfaces: | |||
1739 | * host controller will not allow submissions to dropped endpoints. If | 1762 | * host controller will not allow submissions to dropped endpoints. If |
1740 | * this call fails, the device state is unchanged. | 1763 | * this call fails, the device state is unchanged. |
1741 | */ | 1764 | */ |
1742 | mutex_lock(hcd->bandwidth_mutex); | ||
1743 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); | 1765 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); |
1744 | if (ret < 0) { | 1766 | if (ret < 0) { |
1745 | mutex_unlock(hcd->bandwidth_mutex); | 1767 | mutex_unlock(hcd->bandwidth_mutex); |