diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 34 |
1 files changed, 15 insertions, 19 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 37c67d7e8b84..e1731ff8af4d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -525,15 +525,16 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | |||
525 | 525 | ||
526 | 526 | ||
527 | /* caller has locked the hub device */ | 527 | /* caller has locked the hub device */ |
528 | static void hub_pre_reset(struct usb_hub *hub, int disable_ports) | 528 | static void hub_pre_reset(struct usb_interface *intf) |
529 | { | 529 | { |
530 | struct usb_hub *hub = usb_get_intfdata(intf); | ||
530 | struct usb_device *hdev = hub->hdev; | 531 | struct usb_device *hdev = hub->hdev; |
531 | int port1; | 532 | int port1; |
532 | 533 | ||
533 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | 534 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { |
534 | if (hdev->children[port1 - 1]) { | 535 | if (hdev->children[port1 - 1]) { |
535 | usb_disconnect(&hdev->children[port1 - 1]); | 536 | usb_disconnect(&hdev->children[port1 - 1]); |
536 | if (disable_ports) | 537 | if (hub->error == 0) |
537 | hub_port_disable(hub, port1, 0); | 538 | hub_port_disable(hub, port1, 0); |
538 | } | 539 | } |
539 | } | 540 | } |
@@ -541,8 +542,10 @@ static void hub_pre_reset(struct usb_hub *hub, int disable_ports) | |||
541 | } | 542 | } |
542 | 543 | ||
543 | /* caller has locked the hub device */ | 544 | /* caller has locked the hub device */ |
544 | static void hub_post_reset(struct usb_hub *hub) | 545 | static void hub_post_reset(struct usb_interface *intf) |
545 | { | 546 | { |
547 | struct usb_hub *hub = usb_get_intfdata(intf); | ||
548 | |||
546 | hub_activate(hub); | 549 | hub_activate(hub); |
547 | hub_power_on(hub); | 550 | hub_power_on(hub); |
548 | } | 551 | } |
@@ -802,15 +805,16 @@ static void hub_disconnect(struct usb_interface *intf) | |||
802 | struct usb_hub *hub = usb_get_intfdata (intf); | 805 | struct usb_hub *hub = usb_get_intfdata (intf); |
803 | struct usb_device *hdev; | 806 | struct usb_device *hdev; |
804 | 807 | ||
808 | /* Disconnect all children and quiesce the hub */ | ||
809 | hub->error = 0; | ||
810 | hub_pre_reset(intf); | ||
811 | |||
805 | usb_set_intfdata (intf, NULL); | 812 | usb_set_intfdata (intf, NULL); |
806 | hdev = hub->hdev; | 813 | hdev = hub->hdev; |
807 | 814 | ||
808 | if (hdev->speed == USB_SPEED_HIGH) | 815 | if (hdev->speed == USB_SPEED_HIGH) |
809 | highspeed_hubs--; | 816 | highspeed_hubs--; |
810 | 817 | ||
811 | /* Disconnect all children and quiesce the hub */ | ||
812 | hub_pre_reset(hub, 1); | ||
813 | |||
814 | usb_free_urb(hub->urb); | 818 | usb_free_urb(hub->urb); |
815 | hub->urb = NULL; | 819 | hub->urb = NULL; |
816 | 820 | ||
@@ -2747,7 +2751,8 @@ static void hub_events(void) | |||
2747 | 2751 | ||
2748 | /* If the hub has died, clean up after it */ | 2752 | /* If the hub has died, clean up after it */ |
2749 | if (hdev->state == USB_STATE_NOTATTACHED) { | 2753 | if (hdev->state == USB_STATE_NOTATTACHED) { |
2750 | hub_pre_reset(hub, 0); | 2754 | hub->error = -ENODEV; |
2755 | hub_pre_reset(intf); | ||
2751 | goto loop; | 2756 | goto loop; |
2752 | } | 2757 | } |
2753 | 2758 | ||
@@ -2759,7 +2764,7 @@ static void hub_events(void) | |||
2759 | dev_dbg (hub_dev, "resetting for error %d\n", | 2764 | dev_dbg (hub_dev, "resetting for error %d\n", |
2760 | hub->error); | 2765 | hub->error); |
2761 | 2766 | ||
2762 | ret = usb_reset_device(hdev); | 2767 | ret = usb_reset_composite_device(hdev, intf); |
2763 | if (ret) { | 2768 | if (ret) { |
2764 | dev_dbg (hub_dev, | 2769 | dev_dbg (hub_dev, |
2765 | "error resetting hub: %d\n", ret); | 2770 | "error resetting hub: %d\n", ret); |
@@ -2928,6 +2933,8 @@ static struct usb_driver hub_driver = { | |||
2928 | .disconnect = hub_disconnect, | 2933 | .disconnect = hub_disconnect, |
2929 | .suspend = hub_suspend, | 2934 | .suspend = hub_suspend, |
2930 | .resume = hub_resume, | 2935 | .resume = hub_resume, |
2936 | .pre_reset = hub_pre_reset, | ||
2937 | .post_reset = hub_post_reset, | ||
2931 | .ioctl = hub_ioctl, | 2938 | .ioctl = hub_ioctl, |
2932 | .id_table = hub_id_table, | 2939 | .id_table = hub_id_table, |
2933 | }; | 2940 | }; |
@@ -3033,7 +3040,6 @@ int usb_reset_device(struct usb_device *udev) | |||
3033 | struct usb_device *parent_hdev = udev->parent; | 3040 | struct usb_device *parent_hdev = udev->parent; |
3034 | struct usb_hub *parent_hub; | 3041 | struct usb_hub *parent_hub; |
3035 | struct usb_device_descriptor descriptor = udev->descriptor; | 3042 | struct usb_device_descriptor descriptor = udev->descriptor; |
3036 | struct usb_hub *hub = NULL; | ||
3037 | int i, ret = 0; | 3043 | int i, ret = 0; |
3038 | int port1 = udev->portnum; | 3044 | int port1 = udev->portnum; |
3039 | 3045 | ||
@@ -3051,14 +3057,6 @@ int usb_reset_device(struct usb_device *udev) | |||
3051 | } | 3057 | } |
3052 | parent_hub = hdev_to_hub(parent_hdev); | 3058 | parent_hub = hdev_to_hub(parent_hdev); |
3053 | 3059 | ||
3054 | /* If we're resetting an active hub, take some special actions */ | ||
3055 | if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && | ||
3056 | udev->actconfig->interface[0]->dev.driver == | ||
3057 | &hub_driver.driver && | ||
3058 | (hub = hdev_to_hub(udev)) != NULL) { | ||
3059 | hub_pre_reset(hub, 0); | ||
3060 | } | ||
3061 | |||
3062 | set_bit(port1, parent_hub->busy_bits); | 3060 | set_bit(port1, parent_hub->busy_bits); |
3063 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { | 3061 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { |
3064 | 3062 | ||
@@ -3117,8 +3115,6 @@ int usb_reset_device(struct usb_device *udev) | |||
3117 | } | 3115 | } |
3118 | 3116 | ||
3119 | done: | 3117 | done: |
3120 | if (hub) | ||
3121 | hub_post_reset(hub); | ||
3122 | return 0; | 3118 | return 0; |
3123 | 3119 | ||
3124 | re_enumerate: | 3120 | re_enumerate: |