aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hub.c76
1 files changed, 12 insertions, 64 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 61341d2f3c0e..d3337d9c31dc 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -453,6 +453,7 @@ static void hub_quiesce(struct usb_hub *hub)
453{ 453{
454 /* stop khubd and related activity */ 454 /* stop khubd and related activity */
455 hub->quiescing = 1; 455 hub->quiescing = 1;
456 hub->activating = 0;
456 usb_kill_urb(hub->urb); 457 usb_kill_urb(hub->urb);
457 if (hub->has_indicators) 458 if (hub->has_indicators)
458 cancel_delayed_work(&hub->leds); 459 cancel_delayed_work(&hub->leds);
@@ -1613,68 +1614,21 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
1613 return 0; 1614 return 0;
1614 } 1615 }
1615 1616
1616 /* suspend interface drivers; if this is a hub, it 1617 /* all interfaces must already be suspended */
1617 * suspends the child devices
1618 */
1619 if (udev->actconfig) { 1618 if (udev->actconfig) {
1620 int i; 1619 int i;
1621 1620
1622 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { 1621 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
1623 struct usb_interface *intf; 1622 struct usb_interface *intf;
1624 struct usb_driver *driver;
1625 1623
1626 intf = udev->actconfig->interface[i]; 1624 intf = udev->actconfig->interface[i];
1627 if (!is_active(intf)) 1625 if (is_active(intf)) {
1628 continue; 1626 dev_dbg(&intf->dev, "nyet suspended\n");
1629 if (!intf->dev.driver) 1627 return -EBUSY;
1630 continue;
1631 driver = to_usb_driver(intf->dev.driver);
1632
1633 if (driver->suspend) {
1634 status = driver->suspend(intf, state);
1635 if (status == 0)
1636 mark_quiesced(intf);
1637 else
1638 dev_err(&intf->dev,
1639 "suspend error %d\n",
1640 status);
1641 }
1642
1643 /* only drivers with suspend() can ever resume();
1644 * and after power loss, even they won't.
1645 * bus_rescan_devices() can rebind drivers later.
1646 *
1647 * FIXME the PM core self-deadlocks when unbinding
1648 * drivers during suspend/resume ... everything grabs
1649 * dpm_sem (not a spinlock, ugh). we want to unbind,
1650 * since we know every driver's probe/disconnect works
1651 * even for drivers that can't suspend.
1652 */
1653 if (!driver->suspend || state.event > PM_EVENT_FREEZE) {
1654#if 1
1655 dev_warn(&intf->dev, "resume is unsafe!\n");
1656#else
1657 down_write(&usb_bus_type.rwsem);
1658 device_release_driver(&intf->dev);
1659 up_write(&usb_bus_type.rwsem);
1660#endif
1661 } 1628 }
1662 } 1629 }
1663 } 1630 }
1664 1631
1665 /*
1666 * FIXME this needs port power off call paths too, to help force
1667 * USB into the "generic" PM model. At least for devices on
1668 * ports that aren't using ganged switching (usually root hubs).
1669 *
1670 * NOTE: SRP-capable links should adopt more aggressive poweroff
1671 * policies (when HNP doesn't apply) once we have mechanisms to
1672 * turn power back on! (Likely not before 2.7...)
1673 */
1674 if (state.event > PM_EVENT_FREEZE) {
1675 dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
1676 }
1677
1678 /* "global suspend" of the HC-to-USB interface (root hub), or 1632 /* "global suspend" of the HC-to-USB interface (root hub), or
1679 * "selective suspend" of just one hub-device link. 1633 * "selective suspend" of just one hub-device link.
1680 */ 1634 */
@@ -1960,26 +1914,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
1960 struct usb_hub *hub = usb_get_intfdata (intf); 1914 struct usb_hub *hub = usb_get_intfdata (intf);
1961 struct usb_device *hdev = hub->hdev; 1915 struct usb_device *hdev = hub->hdev;
1962 unsigned port1; 1916 unsigned port1;
1963 int status;
1964
1965 /* stop khubd and related activity */
1966 hub_quiesce(hub);
1967 1917
1968 /* then suspend every port */ 1918 /* fail if children aren't already suspended */
1969 for (port1 = 1; port1 <= hdev->maxchild; port1++) { 1919 for (port1 = 1; port1 <= hdev->maxchild; port1++) {
1970 struct usb_device *udev; 1920 struct usb_device *udev;
1971 1921
1972 udev = hdev->children [port1-1]; 1922 udev = hdev->children [port1-1];
1973 if (!udev) 1923 if (udev && udev->state != USB_STATE_SUSPENDED) {
1974 continue; 1924 dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
1975 down(&udev->serialize); 1925 return -EBUSY;
1976 status = __usb_suspend_device(udev, port1, msg); 1926 }
1977 up(&udev->serialize);
1978 if (status < 0)
1979 dev_dbg(&intf->dev, "suspend port %d --> %d\n",
1980 port1, status);
1981 } 1927 }
1982 1928
1929 /* stop khubd and related activity */
1930 hub_quiesce(hub);
1983 return 0; 1931 return 0;
1984} 1932}
1985 1933