diff options
| -rw-r--r-- | drivers/usb/core/hub.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8eb4da332f56..94789be54ca3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub) | |||
| 644 | 644 | ||
| 645 | #ifdef CONFIG_PM | 645 | #ifdef CONFIG_PM |
| 646 | 646 | ||
| 647 | /* Try to identify which devices need USB-PERSIST handling */ | ||
| 648 | static int persistent_device(struct usb_device *udev) | ||
| 649 | { | ||
| 650 | int i; | ||
| 651 | int retval; | ||
| 652 | struct usb_host_config *actconfig; | ||
| 653 | |||
| 654 | /* Explicitly not marked persistent? */ | ||
| 655 | if (!udev->persist_enabled) | ||
| 656 | return 0; | ||
| 657 | |||
| 658 | /* No active config? */ | ||
| 659 | actconfig = udev->actconfig; | ||
| 660 | if (!actconfig) | ||
| 661 | return 0; | ||
| 662 | |||
| 663 | /* FIXME! We should check whether it's open here or not! */ | ||
| 664 | |||
| 665 | /* | ||
| 666 | * Check that all the interface drivers have a | ||
| 667 | * 'reset_resume' entrypoint | ||
| 668 | */ | ||
| 669 | retval = 0; | ||
| 670 | for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { | ||
| 671 | struct usb_interface *intf; | ||
| 672 | struct usb_driver *driver; | ||
| 673 | |||
| 674 | intf = actconfig->interface[i]; | ||
| 675 | if (!intf->dev.driver) | ||
| 676 | continue; | ||
| 677 | driver = to_usb_driver(intf->dev.driver); | ||
| 678 | if (!driver->reset_resume) | ||
| 679 | return 0; | ||
| 680 | /* | ||
| 681 | * We have at least one driver, and that one | ||
| 682 | * has a reset_resume method. | ||
| 683 | */ | ||
| 684 | retval = 1; | ||
| 685 | } | ||
| 686 | return retval; | ||
| 687 | } | ||
| 688 | |||
| 647 | static void hub_restart(struct usb_hub *hub, int type) | 689 | static void hub_restart(struct usb_hub *hub, int type) |
| 648 | { | 690 | { |
| 649 | struct usb_device *hdev = hub->hdev; | 691 | struct usb_device *hdev = hub->hdev; |
| @@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type) | |||
| 689 | * turn off the various status changes to prevent | 731 | * turn off the various status changes to prevent |
| 690 | * khubd from disconnecting it later. | 732 | * khubd from disconnecting it later. |
| 691 | */ | 733 | */ |
| 692 | if (udev->persist_enabled && status == 0 && | 734 | if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && |
| 693 | !(portstatus & USB_PORT_STAT_ENABLE)) { | 735 | persistent_device(udev)) { |
| 694 | if (portchange & USB_PORT_STAT_C_ENABLE) | 736 | if (portchange & USB_PORT_STAT_C_ENABLE) |
| 695 | clear_port_feature(hub->hdev, port1, | 737 | clear_port_feature(hub->hdev, port1, |
| 696 | USB_PORT_FEAT_C_ENABLE); | 738 | USB_PORT_FEAT_C_ENABLE); |
