aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
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 /drivers/usb/core/driver.c
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>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c71
1 files changed, 42 insertions, 29 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 */