aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-07-01 22:13:04 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:50 -0400
commit114b368c07964caa3f4e1fa575b16e87fa11936c (patch)
tree74500e47040be3bf4923eebd60404fc7b62004a9 /drivers/usb/core/hub.c
parent2bf4086d7a7722b470aa24e1be725cc58619c6fe (diff)
usbcore: fix up device and power state tests
This patch (as734) rationalizes the various tests of device state and power states. There are duplications and mistaken tests in several places. Perhaps the most interesting challenge is where the hub driver tests to see that all the child devices are suspended before allowing itself to be suspended. When CONFIG_USB_SUSPEND is set the test is straightforward, since we expect that the children _will_ be suspended. But when CONFIG_USB_SUSPEND isn't set, it's not so clear what should be done. The code compromises by checking the child's power.power_state.event field. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c47
1 files changed, 10 insertions, 37 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 7af53db4d76..a310c7cede9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1556,26 +1556,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
1556 if (port1 < 0) 1556 if (port1 < 0)
1557 return port1; 1557 return port1;
1558 1558
1559 if (udev->state == USB_STATE_SUSPENDED
1560 || udev->state == USB_STATE_NOTATTACHED) {
1561 return 0;
1562 }
1563
1564 /* all interfaces must already be suspended */
1565 if (udev->actconfig) {
1566 int i;
1567
1568 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
1569 struct usb_interface *intf;
1570
1571 intf = udev->actconfig->interface[i];
1572 if (is_active(intf)) {
1573 dev_dbg(&intf->dev, "nyet suspended\n");
1574 return -EBUSY;
1575 }
1576 }
1577 }
1578
1579 /* we change the device's upstream USB link, 1559 /* we change the device's upstream USB link,
1580 * but root hubs have no upstream USB link. 1560 * but root hubs have no upstream USB link.
1581 */ 1561 */
@@ -1614,8 +1594,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
1614int usb_port_suspend(struct usb_device *udev) 1594int usb_port_suspend(struct usb_device *udev)
1615{ 1595{
1616#ifdef CONFIG_USB_SUSPEND 1596#ifdef CONFIG_USB_SUSPEND
1617 if (udev->state == USB_STATE_NOTATTACHED)
1618 return -ENODEV;
1619 return __usb_port_suspend(udev, udev->portnum); 1597 return __usb_port_suspend(udev, udev->portnum);
1620#else 1598#else
1621 return 0; 1599 return 0;
@@ -1761,24 +1739,17 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
1761 */ 1739 */
1762int usb_port_resume(struct usb_device *udev) 1740int usb_port_resume(struct usb_device *udev)
1763{ 1741{
1764 int status; 1742 int status = 0;
1765
1766 if (udev->state == USB_STATE_NOTATTACHED)
1767 return -ENODEV;
1768 1743
1769 /* we change the device's upstream USB link, 1744 /* we change the device's upstream USB link,
1770 * but root hubs have no upstream USB link. 1745 * but root hubs have no upstream USB link.
1771 */ 1746 */
1772 if (udev->parent) { 1747 if (udev->parent) {
1773#ifdef CONFIG_USB_SUSPEND 1748#ifdef CONFIG_USB_SUSPEND
1774 if (udev->state == USB_STATE_SUSPENDED) { 1749 // NOTE this fails if parent is also suspended...
1775 // NOTE swsusp may bork us, device state being wrong... 1750 status = hub_port_resume(hdev_to_hub(udev->parent),
1776 // NOTE this fails if parent is also suspended... 1751 udev->portnum, udev);
1777 status = hub_port_resume(hdev_to_hub(udev->parent),
1778 udev->portnum, udev);
1779 } else
1780#endif 1752#endif
1781 status = 0;
1782 } else 1753 } else
1783 status = finish_port_resume(udev); 1754 status = finish_port_resume(udev);
1784 if (status < 0) 1755 if (status < 0)
@@ -1821,12 +1792,14 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
1821 struct usb_device *udev; 1792 struct usb_device *udev;
1822 1793
1823 udev = hdev->children [port1-1]; 1794 udev = hdev->children [port1-1];
1824 if (udev && (udev->dev.power.power_state.event 1795 if (udev && msg.event == PM_EVENT_SUSPEND &&
1825 == PM_EVENT_ON
1826#ifdef CONFIG_USB_SUSPEND 1796#ifdef CONFIG_USB_SUSPEND
1827 || udev->state != USB_STATE_SUSPENDED 1797 udev->state != USB_STATE_SUSPENDED
1798#else
1799 udev->dev.power.power_state.event
1800 == PM_EVENT_ON
1828#endif 1801#endif
1829 )) { 1802 ) {
1830 dev_dbg(&intf->dev, "port %d nyet suspended\n", port1); 1803 dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
1831 return -EBUSY; 1804 return -EBUSY;
1832 } 1805 }