aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2005-09-23 01:37:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:40 -0400
commitf3f3253d644d36a2ea5464005a9c2cf28804d200 (patch)
tree913d5d38de9acea02b95c43ea23dc6a28f791236 /drivers/usb/core
parent979d5199fee9e80290ddeb532e5993bd15506712 (diff)
[PATCH] root hub updates (greater half)
This patch associates hub suspend and resume logic (including for root hubs) with CONFIG_PM -- instead of CONFIG_USB_SUSPEND as before -- thereby unifying two troublesome versions of suspend logic into just one. It'll be easier to keep things right from now on. - Now usbcore _always_ calls hcd->hub_suspend as needed, instead of only when USB_SUSPEND is enabled: * Those root hub methods are now called from hub suspend/resume; no more skipping between layers during device suspend/resume; * It now handles cases allowed by sysfs or autosuspended root hubs, by forcing the hub interface to resume too. - All devices, including virtual root hubs, now get the same treatment on their resume paths ... including re-activating all their interfaces. Plus it gets rid of those stub copies of usb_{suspend,resume}_device(), and updates the Kconfig to match the new definition of USB_SUSPEND: it provides (a) selective suspend, downstream from hubs; and (b) remote wakeup, upstream from any device configuration which supports it. This calls for minor followup patches for most HCDs (and their PCI glue). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/core/Kconfig | 11 ++- drivers/usb/core/hub.c | 163 +++++++++++++++++++++++++---------------------- 2 files changed, 97 insertions(+), 77 deletions(-)
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/Kconfig11
-rw-r--r--drivers/usb/core/hub.c163
2 files changed, 97 insertions, 77 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 1a9ff6184943..ff03184da403 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS
61 If you are unsure about this, say N here. 61 If you are unsure about this, say N here.
62 62
63config USB_SUSPEND 63config USB_SUSPEND
64 bool "USB suspend/resume (EXPERIMENTAL)" 64 bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
65 depends on USB && PM && EXPERIMENTAL 65 depends on USB && PM && EXPERIMENTAL
66 help 66 help
67 If you say Y here, you can use driver calls or the sysfs 67 If you say Y here, you can use driver calls or the sysfs
68 "power/state" file to suspend or resume individual USB 68 "power/state" file to suspend or resume individual USB
69 peripherals. There are many related features, such as 69 peripherals.
70 remote wakeup and driver-specific suspend processing, that 70
71 may not yet work as expected. 71 Also, USB "remote wakeup" signaling is supported, whereby some
72 USB devices (like keyboards and network adapters) can wake up
73 their parent hub. That wakeup cascades up the USB tree, and
74 could wake the system from states like suspend-to-RAM.
72 75
73 If you are unsure about this, say N here. 76 If you are unsure about this, say N here.
74 77
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3c8d8d1f993c..6a601a4547e7 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1612,7 +1612,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
1612 */ 1612 */
1613static int __usb_suspend_device (struct usb_device *udev, int port1) 1613static int __usb_suspend_device (struct usb_device *udev, int port1)
1614{ 1614{
1615 int status; 1615 int status = 0;
1616 1616
1617 /* caller owns the udev device lock */ 1617 /* caller owns the udev device lock */
1618 if (port1 < 0) 1618 if (port1 < 0)
@@ -1638,21 +1638,10 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
1638 } 1638 }
1639 } 1639 }
1640 1640
1641 /* "global suspend" of the HC-to-USB interface (root hub), or 1641 /* we only change a device's upstream USB link.
1642 * "selective suspend" of just one hub-device link. 1642 * root hubs have no upstream USB link.
1643 */ 1643 */
1644 if (!udev->parent) { 1644 if (udev->parent)
1645 struct usb_bus *bus = udev->bus;
1646 if (bus && bus->op->hub_suspend) {
1647 status = bus->op->hub_suspend (bus);
1648 if (status == 0) {
1649 dev_dbg(&udev->dev, "usb suspend\n");
1650 usb_set_device_state(udev,
1651 USB_STATE_SUSPENDED);
1652 }
1653 } else
1654 status = -EOPNOTSUPP;
1655 } else
1656 status = hub_port_suspend(hdev_to_hub(udev->parent), port1, 1645 status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
1657 udev); 1646 udev);
1658 1647
@@ -1661,6 +1650,8 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
1661 return status; 1650 return status;
1662} 1651}
1663 1652
1653#endif
1654
1664/** 1655/**
1665 * usb_suspend_device - suspend a usb device 1656 * usb_suspend_device - suspend a usb device
1666 * @udev: device that's no longer in active use 1657 * @udev: device that's no longer in active use
@@ -1683,6 +1674,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
1683 */ 1674 */
1684int usb_suspend_device(struct usb_device *udev) 1675int usb_suspend_device(struct usb_device *udev)
1685{ 1676{
1677#ifdef CONFIG_USB_SUSPEND
1686 int port1, status; 1678 int port1, status;
1687 1679
1688 port1 = locktree(udev); 1680 port1 = locktree(udev);
@@ -1692,8 +1684,14 @@ int usb_suspend_device(struct usb_device *udev)
1692 status = __usb_suspend_device(udev, port1); 1684 status = __usb_suspend_device(udev, port1);
1693 usb_unlock_device(udev); 1685 usb_unlock_device(udev);
1694 return status; 1686 return status;
1687#else
1688 /* NOTE: udev->state unchanged, it's not lying ... */
1689 udev->dev.power.power_state = PMSG_SUSPEND;
1690 return 0;
1691#endif
1695} 1692}
1696 1693
1694
1697/* 1695/*
1698 * If the USB "suspend" state is in use (rather than "global suspend"), 1696 * If the USB "suspend" state is in use (rather than "global suspend"),
1699 * many devices will be individually taken out of suspend state using 1697 * many devices will be individually taken out of suspend state using
@@ -1702,13 +1700,13 @@ int usb_suspend_device(struct usb_device *udev)
1702 * resume (by host) or remote wakeup (by device) ... now see what changed 1700 * resume (by host) or remote wakeup (by device) ... now see what changed
1703 * in the tree that's rooted at this device. 1701 * in the tree that's rooted at this device.
1704 */ 1702 */
1705static int finish_port_resume(struct usb_device *udev) 1703static int finish_device_resume(struct usb_device *udev)
1706{ 1704{
1707 int status; 1705 int status;
1708 u16 devstatus; 1706 u16 devstatus;
1709 1707
1710 /* caller owns the udev device lock */ 1708 /* caller owns the udev device lock */
1711 dev_dbg(&udev->dev, "usb resume\n"); 1709 dev_dbg(&udev->dev, "finish resume\n");
1712 1710
1713 /* usb ch9 identifies four variants of SUSPENDED, based on what 1711 /* usb ch9 identifies four variants of SUSPENDED, based on what
1714 * state the device resumes to. Linux currently won't see the 1712 * state the device resumes to. Linux currently won't see the
@@ -1718,7 +1716,6 @@ static int finish_port_resume(struct usb_device *udev)
1718 usb_set_device_state(udev, udev->actconfig 1716 usb_set_device_state(udev, udev->actconfig
1719 ? USB_STATE_CONFIGURED 1717 ? USB_STATE_CONFIGURED
1720 : USB_STATE_ADDRESS); 1718 : USB_STATE_ADDRESS);
1721 udev->dev.power.power_state = PMSG_ON;
1722 1719
1723 /* 10.5.4.5 says be sure devices in the tree are still there. 1720 /* 10.5.4.5 says be sure devices in the tree are still there.
1724 * For now let's assume the device didn't go crazy on resume, 1721 * For now let's assume the device didn't go crazy on resume,
@@ -1734,7 +1731,8 @@ static int finish_port_resume(struct usb_device *udev)
1734 int (*resume)(struct device *); 1731 int (*resume)(struct device *);
1735 1732
1736 le16_to_cpus(&devstatus); 1733 le16_to_cpus(&devstatus);
1737 if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { 1734 if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
1735 && udev->parent) {
1738 status = usb_control_msg(udev, 1736 status = usb_control_msg(udev,
1739 usb_sndctrlpipe(udev, 0), 1737 usb_sndctrlpipe(udev, 0),
1740 USB_REQ_CLEAR_FEATURE, 1738 USB_REQ_CLEAR_FEATURE,
@@ -1764,6 +1762,8 @@ static int finish_port_resume(struct usb_device *udev)
1764 return status; 1762 return status;
1765} 1763}
1766 1764
1765#ifdef CONFIG_USB_SUSPEND
1766
1767static int 1767static int
1768hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) 1768hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
1769{ 1769{
@@ -1809,7 +1809,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
1809 /* TRSMRCY = 10 msec */ 1809 /* TRSMRCY = 10 msec */
1810 msleep(10); 1810 msleep(10);
1811 if (udev) 1811 if (udev)
1812 status = finish_port_resume(udev); 1812 status = finish_device_resume(udev);
1813 } 1813 }
1814 } 1814 }
1815 if (status < 0) 1815 if (status < 0)
@@ -1818,7 +1818,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
1818 return status; 1818 return status;
1819} 1819}
1820 1820
1821static int hub_resume (struct usb_interface *intf); 1821#endif
1822