aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-11-21 11:58:07 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:34 -0500
commit4bf0ba861442d289eebfad8ea9ce365ab04fd582 (patch)
tree0301e45a155712ec03e0226a1e85e74198778f7e /drivers
parent7d069b7d80933004282c48edbe62526e4cb0aecc (diff)
[PATCH] USB: Fix locking for USB suspend/resume
The earlier USB locking updates didn't touch the suspend/resume routines. They need updating as well, since now the caller holds the device semaphore. This patch (as608) makes the necessary changes. It also adds a line to store the correct power state when a device is resumed, something which was unaccountably missing. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/hub.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 02601f412f9d..895ac829b9cf 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1648,15 +1648,22 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
1648int usb_suspend_device(struct usb_device *udev) 1648int usb_suspend_device(struct usb_device *udev)
1649{ 1649{
1650#ifdef CONFIG_USB_SUSPEND 1650#ifdef CONFIG_USB_SUSPEND
1651 int port1, status; 1651 int port1;
1652 1652
1653 port1 = locktree(udev); 1653 if (udev->state == USB_STATE_NOTATTACHED)
1654 if (port1 < 0) 1654 return -ENODEV;
1655 return port1; 1655 if (!udev->parent)
1656 port1 = 0;
1657 else {
1658 for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
1659 if (udev->parent->children[port1-1] == udev)
1660 break;
1661 }
1662 if (port1 == 0)
1663 return -ENODEV;
1664 }
1656 1665
1657 status = __usb_suspend_device(udev, port1); 1666 return __usb_suspend_device(udev, port1);
1658 usb_unlock_device(udev);
1659 return status;
1660#else 1667#else
1661 /* NOTE: udev->state unchanged, it's not lying ... */ 1668 /* NOTE: udev->state unchanged, it's not lying ... */
1662 udev->dev.power.power_state = PMSG_SUSPEND; 1669 udev->dev.power.power_state = PMSG_SUSPEND;
@@ -1688,6 +1695,7 @@ static int finish_device_resume(struct usb_device *udev)
1688 usb_set_device_state(udev, udev->actconfig 1695 usb_set_device_state(udev, udev->actconfig
1689 ? USB_STATE_CONFIGURED 1696 ? USB_STATE_CONFIGURED
1690 : USB_STATE_ADDRESS); 1697 : USB_STATE_ADDRESS);
1698 udev->dev.power.power_state = PMSG_ON;
1691 1699
1692 /* 10.5.4.5 says be sure devices in the tree are still there. 1700 /* 10.5.4.5 says be sure devices in the tree are still there.
1693 * For now let's assume the device didn't go crazy on resume, 1701 * For now let's assume the device didn't go crazy on resume,
@@ -1723,8 +1731,14 @@ static int finish_device_resume(struct usb_device *udev)
1723 * may have a child resume event to deal with soon 1731 * may have a child resume event to deal with soon
1724 */ 1732 */
1725 resume = udev->dev.bus->resume; 1733 resume = udev->dev.bus->resume;
1726 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) 1734 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
1727 (void) resume(&udev->actconfig->interface[i]->dev); 1735 struct device *dev =
1736 &udev->actconfig->interface[i]->dev;
1737
1738 down(&dev->sem);
1739 (void) resume(dev);
1740 up(&dev->sem);
1741 }
1728 status = 0; 1742 status = 0;
1729 1743
1730 } else if (udev->devnum <= 0) { 1744 } else if (udev->devnum <= 0) {
@@ -1809,9 +1823,18 @@ int usb_resume_device(struct usb_device *udev)
1809{ 1823{
1810 int port1, status; 1824 int port1, status;
1811 1825
1812 port1 = locktree(udev); 1826 if (udev->state == USB_STATE_NOTATTACHED)
1813 if (port1 < 0) 1827 return -ENODEV;
1814 return port1; 1828 if (!udev->parent)
1829 port1 = 0;
1830 else {
1831 for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
1832 if (udev->parent->children[port1-1] == udev)
1833 break;
1834 }
1835 if (port1 == 0)
1836 return -ENODEV;
1837 }
1815 1838
1816#ifdef CONFIG_USB_SUSPEND 1839#ifdef CONFIG_USB_SUSPEND
1817 /* selective resume of one downstream hub-to-device port */ 1840 /* selective resume of one downstream hub-to-device port */
@@ -1830,11 +1853,12 @@ int usb_resume_device(struct usb_device *udev)
1830 dev_dbg(&udev->dev, "can't resume, status %d\n", 1853 dev_dbg(&udev->dev, "can't resume, status %d\n",
1831 status); 1854 status);
1832 1855
1833 usb_unlock_device(udev);
1834
1835 /* rebind drivers that had no suspend() */ 1856 /* rebind drivers that had no suspend() */
1836 if (status == 0) 1857 if (status == 0) {
1858 usb_unlock_device(udev);
1837 bus_rescan_devices(&usb_bus_type); 1859 bus_rescan_devices(&usb_bus_type);
1860 usb_lock_device(udev);
1861 }
1838 return status; 1862 return status;
1839} 1863}
1840 1864