aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-07-01 22:12:19 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:50 -0400
commit2bf4086d7a7722b470aa24e1be725cc58619c6fe (patch)
tree26724ce626c7b522311d7f9993527a8d2a0268fd
parent4d064c080265a41324d108fccc26b72106d43db3 (diff)
usbcore: set device and power states properly
This patch (as733) fixes up the places where device states and power states are set in usbcore. Right now things are duplicated or missing; this should straighten things out. The idea is that udev->state is USB_STATE_SUSPENDED exactly when the device's upstream port has been suspended, whereas udev->dev.power.power_state.event reflects the result of the last call to the suspend/resume routines (which might not actually change the device state, especially if CONFIG_USB_SUSPEND isn't set). Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/driver.c71
-rw-r--r--drivers/usb/core/hub.c10
2 files changed, 46 insertions, 35 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index eefc98584eac..92ecc4eb1e88 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -755,48 +755,57 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
755static int suspend_device(struct usb_device *udev, pm_message_t msg) 755static int suspend_device(struct usb_device *udev, pm_message_t msg)
756{ 756{
757 struct usb_device_driver *udriver; 757 struct usb_device_driver *udriver;
758 int status = 0;
758 759
759 if (udev->dev.driver == NULL) 760 if (udev->dev.driver == NULL)
760 return 0; 761 goto done;
761 udriver = to_usb_device_driver(udev->dev.driver); 762 udriver = to_usb_device_driver(udev->dev.driver);
762 if (udev->dev.power.power_state.event == msg.event) 763 if (udev->dev.power.power_state.event == msg.event)
763 return 0; 764 goto done;
764 return udriver->suspend(udev, msg); 765 status = udriver->suspend(udev, msg);
766
767done:
768 if (status == 0)
769 udev->dev.power.power_state.event = msg.event;
770 return status;
765} 771}
766 772
767/* Caller has locked udev */ 773/* Caller has locked udev */
768static int resume_device(struct usb_device *udev) 774static int resume_device(struct usb_device *udev)
769{ 775{
770 struct usb_device_driver *udriver; 776 struct usb_device_driver *udriver;
777 int status = 0;
771 778
772 if (udev->dev.power.power_state.event == PM_EVENT_ON) 779 if (udev->dev.power.power_state.event == PM_EVENT_ON)
773 return 0; 780 goto done;
774
775 /* mark things as "on" immediately, no matter what errors crop up */
776 udev->dev.power.power_state.event = PM_EVENT_ON;
777 781
778 if (udev->dev.driver == NULL) 782 if (udev->dev.driver == NULL)
779 return 0; 783 goto done;
780 udriver = to_usb_device_driver(udev->dev.driver); 784 udriver = to_usb_device_driver(udev->dev.driver);
781 if (udev->state == USB_STATE_NOTATTACHED) 785 if (udev->state == USB_STATE_NOTATTACHED)
782 return 0; 786 goto done;
783 return udriver->resume(udev); 787 status = udriver->resume(udev);
788
789done:
790 if (status == 0)
791 udev->dev.power.power_state.event = PM_EVENT_ON;
792 return status;
784} 793}
785 794
786/* Caller has locked intf's usb_device */ 795/* Caller has locked intf's usb_device */
787static int suspend_interface(struct usb_interface *intf, pm_message_t msg) 796static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
788{ 797{
789 struct usb_driver *driver; 798 struct usb_driver *driver;
790 int status; 799 int status = 0;
791 800
792 if (intf->dev.driver == NULL) 801 if (intf->dev.driver == NULL)
793 return 0; 802 goto done;
794 803
795 driver = to_usb_driver(intf->dev.driver); 804 driver = to_usb_driver(intf->dev.driver);
796 805
797 /* with no hardware, USB interfaces only use FREEZE and ON states */ 806 /* with no hardware, USB interfaces only use FREEZE and ON states */
798 if (!is_active(intf)) 807 if (!is_active(intf))
799 return 0; 808 goto done;
800 809
801 if (driver->suspend && driver->resume) { 810 if (driver->suspend && driver->resume) {
802 status = driver->suspend(intf, msg); 811 status = driver->suspend(intf, msg);
@@ -810,8 +819,11 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
810 dev_warn(&intf->dev, "no suspend for driver %s?\n", 819 dev_warn(&intf->dev, "no suspend for driver %s?\n",
811 driver->name); 820 driver->name);
812 mark_quiesced(intf); 821 mark_quiesced(intf);
813 status = 0;
814 } 822 }
823
824done:
825 if (status == 0)
826 intf->dev.power.power_state.event = msg.event;
815 return status; 827 return status;
816} 828}
817 829
@@ -820,24 +832,19 @@ static int resume_interface(struct usb_interface *intf)
820{ 832{
821 struct usb_driver *driver; 833 struct usb_driver *driver;
822 struct usb_device *udev; 834 struct usb_device *udev;
823 int status; 835 int status = 0;
824 836
825 if (intf->dev.power.power_state.event == PM_EVENT_ON) 837 if (intf->dev.power.power_state.event == PM_EVENT_ON)
826 return 0; 838 goto done;
827
828 /* mark things as "on" immediately, no matter what errors crop up */
829 intf->dev.power.power_state.event = PM_EVENT_ON;
830 839
831 if (intf->dev.driver == NULL) { 840 if (intf->dev.driver == NULL)
832 intf->dev.power.power_state.event = PM_EVENT_FREEZE; 841 goto done;
833 return 0;
834 }
835 842
836 driver = to_usb_driver(intf->dev.driver); 843 driver = to_usb_driver(intf->dev.driver);
837 844
838 udev = interface_to_usbdev(intf); 845 udev = interface_to_usbdev(intf);
839 if (udev->state == USB_STATE_NOTATTACHED) 846 if (udev->state == USB_STATE_NOTATTACHED)
840 return 0; 847 goto done;
841 848
842 /* if driver was suspended, it has a resume method; 849 /* if driver was suspended, it has a resume method;
843 * however, sysfs can wrongly mark things as suspended 850 * however, sysfs can wrongly mark things as suspended
@@ -845,15 +852,21 @@ static int resume_interface(struct usb_interface *intf)
845 */ 852 */
846 if (driver->resume) { 853 if (driver->resume) {
847 status = driver->resume(intf); 854 status = driver->resume(intf);
848 if (status) { 855 if (status)
849 dev_err(&intf->dev, "%s error %d\n", 856 dev_err(&intf->dev, "%s error %d\n",
850 "resume", status); 857 "resume", status);
851 mark_quiesced(intf); 858 else
852 } 859 mark_active(intf);
853 } else 860 } else {
854 dev_warn(&intf->dev, "no resume for driver %s?\n", 861 dev_warn(&intf->dev, "no resume for driver %s?\n",
855 driver->name); 862 driver->name);
856 return 0; 863 mark_active(intf);
864 }
865
866done:
867 if (status == 0)
868 intf->dev.power.power_state.event = PM_EVENT_ON;
869 return status;
857} 870}
858 871
859/* Caller has locked udev */ 872/* Caller has locked udev */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a39112041e69..7af53db4d76f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1582,9 +1582,10 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
1582 if (udev->parent) 1582 if (udev->parent)
1583 status = hub_port_suspend(hdev_to_hub(udev->parent), port1, 1583 status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
1584 udev); 1584 udev);
1585 1585 else {
1586 if (status == 0) 1586 dev_dbg(&udev->dev, "usb suspend\n");
1587 udev->dev.power.power_state = PMSG_SUSPEND; 1587 usb_set_device_state(udev, USB_STATE_SUSPENDED);
1588 }
1588 return status; 1589 return status;
1589} 1590}
1590 1591
@@ -1617,8 +1618,6 @@ int usb_port_suspend(struct usb_device *udev)
1617 return -ENODEV; 1618 return -ENODEV;
1618 return __usb_port_suspend(udev, udev->portnum); 1619 return __usb_port_suspend(udev, udev->portnum);
1619#else 1620#else
1620 /* NOTE: udev->state unchanged, it's not lying ... */
1621 udev->dev.power.power_state = PMSG_SUSPEND;
1622 return 0; 1621 return 0;
1623#endif 1622#endif
1624} 1623}
@@ -1647,7 +1646,6 @@ static int finish_port_resume(struct usb_device *udev)
1647 usb_set_device_state(udev, udev->actconfig 1646 usb_set_device_state(udev, udev->actconfig
1648 ? USB_STATE_CONFIGURED 1647 ? USB_STATE_CONFIGURED
1649 : USB_STATE_ADDRESS); 1648 : USB_STATE_ADDRESS);
1650 udev->dev.power.power_state = PMSG_ON;
1651 1649
1652 /* 10.5.4.5 says be sure devices in the tree are still there. 1650 /* 10.5.4.5 says be sure devices in the tree are still there.
1653 * For now let's assume the device didn't go crazy on resume, 1651 * For now let's assume the device didn't go crazy on resume,