diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/driver.c | 40 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 47 |
3 files changed, 29 insertions, 61 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 92ecc4eb1e88..affbfb53eb5e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -757,11 +757,13 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg) | |||
757 | struct usb_device_driver *udriver; | 757 | struct usb_device_driver *udriver; |
758 | int status = 0; | 758 | int status = 0; |
759 | 759 | ||
760 | if (udev->state == USB_STATE_NOTATTACHED || | ||
761 | udev->state == USB_STATE_SUSPENDED) | ||
762 | goto done; | ||
763 | |||
760 | if (udev->dev.driver == NULL) | 764 | if (udev->dev.driver == NULL) |
761 | goto done; | 765 | goto done; |
762 | udriver = to_usb_device_driver(udev->dev.driver); | 766 | udriver = to_usb_device_driver(udev->dev.driver); |
763 | if (udev->dev.power.power_state.event == msg.event) | ||
764 | goto done; | ||
765 | status = udriver->suspend(udev, msg); | 767 | status = udriver->suspend(udev, msg); |
766 | 768 | ||
767 | done: | 769 | done: |
@@ -776,14 +778,13 @@ static int resume_device(struct usb_device *udev) | |||
776 | struct usb_device_driver *udriver; | 778 | struct usb_device_driver *udriver; |
777 | int status = 0; | 779 | int status = 0; |
778 | 780 | ||
779 | if (udev->dev.power.power_state.event == PM_EVENT_ON) | 781 | if (udev->state == USB_STATE_NOTATTACHED || |
782 | udev->state != USB_STATE_SUSPENDED) | ||
780 | goto done; | 783 | goto done; |
781 | 784 | ||
782 | if (udev->dev.driver == NULL) | 785 | if (udev->dev.driver == NULL) |
783 | goto done; | 786 | goto done; |
784 | udriver = to_usb_device_driver(udev->dev.driver); | 787 | udriver = to_usb_device_driver(udev->dev.driver); |
785 | if (udev->state == USB_STATE_NOTATTACHED) | ||
786 | goto done; | ||
787 | status = udriver->resume(udev); | 788 | status = udriver->resume(udev); |
788 | 789 | ||
789 | done: | 790 | done: |
@@ -798,14 +799,14 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg) | |||
798 | struct usb_driver *driver; | 799 | struct usb_driver *driver; |
799 | int status = 0; | 800 | int status = 0; |
800 | 801 | ||
801 | if (intf->dev.driver == NULL) | 802 | /* with no hardware, USB interfaces only use FREEZE and ON states */ |
803 | if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || | ||
804 | !is_active(intf)) | ||
802 | goto done; | 805 | goto done; |
803 | 806 | ||
804 | driver = to_usb_driver(intf->dev.driver); | 807 | if (intf->dev.driver == NULL) |
805 | |||
806 | /* with no hardware, USB interfaces only use FREEZE and ON states */ | ||
807 | if (!is_active(intf)) | ||
808 | goto done; | 808 | goto done; |
809 | driver = to_usb_driver(intf->dev.driver); | ||
809 | 810 | ||
810 | if (driver->suspend && driver->resume) { | 811 | if (driver->suspend && driver->resume) { |
811 | status = driver->suspend(intf, msg); | 812 | status = driver->suspend(intf, msg); |
@@ -831,25 +832,16 @@ done: | |||
831 | static int resume_interface(struct usb_interface *intf) | 832 | static int resume_interface(struct usb_interface *intf) |
832 | { | 833 | { |
833 | struct usb_driver *driver; | 834 | struct usb_driver *driver; |
834 | struct usb_device *udev; | ||
835 | int status = 0; | 835 | int status = 0; |
836 | 836 | ||
837 | if (intf->dev.power.power_state.event == PM_EVENT_ON) | 837 | if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || |
838 | is_active(intf)) | ||
838 | goto done; | 839 | goto done; |
839 | 840 | ||
840 | if (intf->dev.driver == NULL) | 841 | if (intf->dev.driver == NULL) |
841 | goto done; | 842 | goto done; |
842 | |||
843 | driver = to_usb_driver(intf->dev.driver); | 843 | driver = to_usb_driver(intf->dev.driver); |
844 | 844 | ||
845 | udev = interface_to_usbdev(intf); | ||
846 | if (udev->state == USB_STATE_NOTATTACHED) | ||
847 | goto done; | ||
848 | |||
849 | /* if driver was suspended, it has a resume method; | ||
850 | * however, sysfs can wrongly mark things as suspended | ||
851 | * (on the "no suspend method" FIXME path above) | ||
852 | */ | ||
853 | if (driver->resume) { | 845 | if (driver->resume) { |
854 | status = driver->resume(intf); | 846 | status = driver->resume(intf); |
855 | if (status) | 847 | if (status) |
@@ -904,6 +896,12 @@ int usb_resume_both(struct usb_device *udev) | |||
904 | int i; | 896 | int i; |
905 | struct usb_interface *intf; | 897 | struct usb_interface *intf; |
906 | 898 | ||
899 | /* Can't resume if the parent is suspended */ | ||
900 | if (udev->parent && udev->parent->state == USB_STATE_SUSPENDED) { | ||
901 | dev_warn(&udev->dev, "can't resume; parent is suspended\n"); | ||
902 | return -EHOSTUNREACH; | ||
903 | } | ||
904 | |||
907 | status = resume_device(udev); | 905 | status = resume_device(udev); |
908 | if (status == 0 && udev->actconfig) { | 906 | if (status == 0 && udev->actconfig) { |
909 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 907 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index b6dacd7551d2..5358e656477c 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -195,9 +195,6 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) | |||
195 | 195 | ||
196 | static int generic_resume(struct usb_device *udev) | 196 | static int generic_resume(struct usb_device *udev) |
197 | { | 197 | { |
198 | if (udev->state == USB_STATE_NOTATTACHED) | ||
199 | return 0; | ||
200 | |||
201 | return usb_port_resume(udev); | 198 | return usb_port_resume(udev); |
202 | } | 199 | } |
203 | 200 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7af53db4d76f..a310c7cede99 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 | } |