diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-07-01 22:13:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:50 -0400 |
commit | 114b368c07964caa3f4e1fa575b16e87fa11936c (patch) | |
tree | 74500e47040be3bf4923eebd60404fc7b62004a9 /drivers/usb/core/hub.c | |
parent | 2bf4086d7a7722b470aa24e1be725cc58619c6fe (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.c | 47 |
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) | |||
1614 | int usb_port_suspend(struct usb_device *udev) | 1594 | int 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 | */ |
1762 | int usb_port_resume(struct usb_device *udev) | 1740 | int 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 | } |