aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/driver.c40
-rw-r--r--drivers/usb/core/generic.c3
-rw-r--r--drivers/usb/core/hub.c47
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
767done: 769done:
@@ -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
789done: 790done:
@@ -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:
831static int resume_interface(struct usb_interface *intf) 832static 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
196static int generic_resume(struct usb_device *udev) 196static 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)
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 }