diff options
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 69 |
1 files changed, 34 insertions, 35 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 0d4b5dcee3ab..a62de0a85406 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -530,9 +530,10 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
530 | /* driver is often null here; dev_dbg() would oops */ | 530 | /* driver is often null here; dev_dbg() would oops */ |
531 | pr_debug ("usb %s: uevent\n", dev->bus_id); | 531 | pr_debug ("usb %s: uevent\n", dev->bus_id); |
532 | 532 | ||
533 | if (is_usb_device(dev)) | 533 | if (is_usb_device(dev)) { |
534 | return 0; | 534 | usb_dev = to_usb_device(dev); |
535 | else { | 535 | alt = NULL; |
536 | } else { | ||
536 | intf = to_usb_interface(dev); | 537 | intf = to_usb_interface(dev); |
537 | usb_dev = interface_to_usbdev(intf); | 538 | usb_dev = interface_to_usbdev(intf); |
538 | alt = intf->cur_altsetting; | 539 | alt = intf->cur_altsetting; |
@@ -579,15 +580,17 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
579 | usb_dev->descriptor.bDeviceProtocol)) | 580 | usb_dev->descriptor.bDeviceProtocol)) |
580 | return -ENOMEM; | 581 | return -ENOMEM; |
581 | 582 | ||
582 | if (add_uevent_var(envp, num_envp, &i, | 583 | if (!is_usb_device(dev)) { |
584 | |||
585 | if (add_uevent_var(envp, num_envp, &i, | ||
583 | buffer, buffer_size, &length, | 586 | buffer, buffer_size, &length, |
584 | "INTERFACE=%d/%d/%d", | 587 | "INTERFACE=%d/%d/%d", |
585 | alt->desc.bInterfaceClass, | 588 | alt->desc.bInterfaceClass, |
586 | alt->desc.bInterfaceSubClass, | 589 | alt->desc.bInterfaceSubClass, |
587 | alt->desc.bInterfaceProtocol)) | 590 | alt->desc.bInterfaceProtocol)) |
588 | return -ENOMEM; | 591 | return -ENOMEM; |
589 | 592 | ||
590 | if (add_uevent_var(envp, num_envp, &i, | 593 | if (add_uevent_var(envp, num_envp, &i, |
591 | buffer, buffer_size, &length, | 594 | buffer, buffer_size, &length, |
592 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | 595 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", |
593 | le16_to_cpu(usb_dev->descriptor.idVendor), | 596 | le16_to_cpu(usb_dev->descriptor.idVendor), |
@@ -599,7 +602,8 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
599 | alt->desc.bInterfaceClass, | 602 | alt->desc.bInterfaceClass, |
600 | alt->desc.bInterfaceSubClass, | 603 | alt->desc.bInterfaceSubClass, |
601 | alt->desc.bInterfaceProtocol)) | 604 | alt->desc.bInterfaceProtocol)) |
602 | return -ENOMEM; | 605 | return -ENOMEM; |
606 | } | ||
603 | 607 | ||
604 | envp[i] = NULL; | 608 | envp[i] = NULL; |
605 | 609 | ||
@@ -747,31 +751,22 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); | |||
747 | 751 | ||
748 | #ifdef CONFIG_PM | 752 | #ifdef CONFIG_PM |
749 | 753 | ||
750 | static int verify_suspended(struct device *dev, void *unused) | 754 | static int usb_suspend(struct device *dev, pm_message_t message) |
751 | { | 755 | { |
752 | if (dev->driver == NULL) | 756 | struct usb_device *udev; |
753 | return 0; | 757 | struct usb_device_driver *udriver; |
754 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | 758 | struct usb_interface *intf; |
755 | } | 759 | struct usb_driver *driver; |
760 | int status; | ||
756 | 761 | ||
757 | static int usb_generic_suspend(struct device *dev, pm_message_t message) | ||
758 | { | ||
759 | struct usb_interface *intf; | ||
760 | struct usb_driver *driver; | ||
761 | int status; | ||
762 | |||
763 | /* USB devices enter SUSPEND state through their hubs, but can be | ||
764 | * marked for FREEZE as soon as their children are already idled. | ||
765 | * But those semantics are useless, so we equate the two (sigh). | ||
766 | */ | ||
767 | if (is_usb_device(dev)) { | 762 | if (is_usb_device(dev)) { |
763 | if (dev->driver == NULL) | ||
764 | return 0; | ||
765 | udev = to_usb_device(dev); | ||
766 | udriver = to_usb_device_driver(dev->driver); | ||
768 | if (dev->power.power_state.event == message.event) | 767 | if (dev->power.power_state.event == message.event) |
769 | return 0; | 768 | return 0; |
770 | /* we need to rule out bogus requests through sysfs */ | 769 | return udriver->suspend(udev, message); |
771 | status = device_for_each_child(dev, NULL, verify_suspended); | ||
772 | if (status) | ||
773 | return status; | ||
774 | return usb_port_suspend(to_usb_device(dev)); | ||
775 | } | 770 | } |
776 | 771 | ||
777 | if (dev->driver == NULL) | 772 | if (dev->driver == NULL) |
@@ -799,12 +794,13 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) | |||
799 | return status; | 794 | return status; |
800 | } | 795 | } |
801 | 796 | ||
802 | static int usb_generic_resume(struct device *dev) | 797 | static int usb_resume(struct device *dev) |
803 | { | 798 | { |
804 | struct usb_interface *intf; | 799 | struct usb_device *udev; |
805 | struct usb_driver *driver; | 800 | struct usb_device_driver *udriver; |
806 | struct usb_device *udev; | 801 | struct usb_interface *intf; |
807 | int status; | 802 | struct usb_driver *driver; |
803 | int status; | ||
808 | 804 | ||
809 | if (dev->power.power_state.event == PM_EVENT_ON) | 805 | if (dev->power.power_state.event == PM_EVENT_ON) |
810 | return 0; | 806 | return 0; |
@@ -814,10 +810,13 @@ static int usb_generic_resume(struct device *dev) | |||
814 | 810 | ||
815 | /* devices resume through their hubs */ | 811 | /* devices resume through their hubs */ |
816 | if (is_usb_device(dev)) { | 812 | if (is_usb_device(dev)) { |
813 | if (dev->driver == NULL) | ||
814 | return 0; | ||
817 | udev = to_usb_device(dev); | 815 | udev = to_usb_device(dev); |
816 | udriver = to_usb_device_driver(dev->driver); | ||
818 | if (udev->state == USB_STATE_NOTATTACHED) | 817 | if (udev->state == USB_STATE_NOTATTACHED) |
819 | return 0; | 818 | return 0; |
820 | return usb_port_resume(udev); | 819 | return udriver->resume(udev); |
821 | } | 820 | } |
822 | 821 | ||
823 | if (dev->driver == NULL) { | 822 | if (dev->driver == NULL) { |
@@ -854,7 +853,7 @@ struct bus_type usb_bus_type = { | |||
854 | .match = usb_device_match, | 853 | .match = usb_device_match, |
855 | .uevent = usb_uevent, | 854 | .uevent = usb_uevent, |
856 | #ifdef CONFIG_PM | 855 | #ifdef CONFIG_PM |
857 | .suspend = usb_generic_suspend, | 856 | .suspend = usb_suspend, |
858 | .resume = usb_generic_resume, | 857 | .resume = usb_resume, |
859 | #endif | 858 | #endif |
860 | }; | 859 | }; |