aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hub.c91
1 files changed, 81 insertions, 10 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d99963873e37..b97110ca352d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -77,6 +77,7 @@ struct usb_hub {
77 unsigned has_indicators:1; 77 unsigned has_indicators:1;
78 u8 indicator[USB_MAXCHILDREN]; 78 u8 indicator[USB_MAXCHILDREN];
79 struct delayed_work leds; 79 struct delayed_work leds;
80 struct delayed_work init_work;
80}; 81};
81 82
82 83
@@ -515,10 +516,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
515} 516}
516EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer); 517EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
517 518
518static void hub_power_on(struct usb_hub *hub) 519/* If do_delay is false, return the number of milliseconds the caller
520 * needs to delay.
521 */
522static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
519{ 523{
520 int port1; 524 int port1;
521 unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; 525 unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
526 unsigned delay;
522 u16 wHubCharacteristics = 527 u16 wHubCharacteristics =
523 le16_to_cpu(hub->descriptor->wHubCharacteristics); 528 le16_to_cpu(hub->descriptor->wHubCharacteristics);
524 529
@@ -537,7 +542,10 @@ static void hub_power_on(struct usb_hub *hub)
537 set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); 542 set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
538 543
539 /* Wait at least 100 msec for power to become stable */ 544 /* Wait at least 100 msec for power to become stable */
540 msleep(max(pgood_delay, (unsigned) 100)); 545 delay = max(pgood_delay, (unsigned) 100);
546 if (do_delay)
547 msleep(delay);
548 return delay;
541} 549}
542 550
543static int hub_hub_status(struct usb_hub *hub, 551static int hub_hub_status(struct usb_hub *hub,
@@ -599,21 +607,55 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
599} 607}
600 608
601enum hub_activation_type { 609enum hub_activation_type {
602 HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME 610 HUB_INIT, HUB_INIT2, HUB_INIT3,
611 HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
603}; 612};
604 613
614static void hub_init_func2(struct work_struct *ws);
615static void hub_init_func3(struct work_struct *ws);
616
605static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) 617static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
606{ 618{
607 struct usb_device *hdev = hub->hdev; 619 struct usb_device *hdev = hub->hdev;
608 int port1; 620 int port1;
609 int status; 621 int status;
610 bool need_debounce_delay = false; 622 bool need_debounce_delay = false;
623 unsigned delay;
624
625 /* Continue a partial initialization */
626 if (type == HUB_INIT2)
627 goto init2;
628 if (type == HUB_INIT3)
629 goto init3;
611 630
612 /* After a resume, port power should still be on. 631 /* After a resume, port power should still be on.
613 * For any other type of activation, turn it on. 632 * For any other type of activation, turn it on.
614 */ 633 */
615 if (type != HUB_RESUME) 634 if (type != HUB_RESUME) {
616 hub_power_on(hub); 635
636 /* Speed up system boot by using a delayed_work for the
637 * hub's initial power-up delays. This is pretty awkward
638 * and the implementation looks like a home-brewed sort of
639 * setjmp/longjmp, but it saves at least 100 ms for each
640 * root hub (assuming usbcore is compiled into the kernel
641 * rather than as a module). It adds up.
642 *
643 * This can't be done for HUB_RESUME or HUB_RESET_RESUME
644 * because for those activation types the ports have to be
645 * operational when we return. In theory this could be done
646 * for HUB_POST_RESET, but it's easier not to.
647 */
648 if (type == HUB_INIT) {
649 delay = hub_power_on(hub, false);
650 PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
651 schedule_delayed_work(&hub->init_work,
652 msecs_to_jiffies(delay));
653 return; /* Continues at init2: below */
654 } else {
655 hub_power_on(hub, true);
656 }
657 }
658 init2:
617 659
618 /* Check each port and set hub->change_bits to let khubd know 660 /* Check each port and set hub->change_bits to let khubd know
619 * which ports need attention. 661 * which ports need attention.
@@ -692,9 +734,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
692 * If any port-status changes do occur during this delay, khubd 734 * If any port-status changes do occur during this delay, khubd
693 * will see them later and handle them normally. 735 * will see them later and handle them normally.
694 */ 736 */
695 if (need_debounce_delay) 737 if (need_debounce_delay) {
696 msleep(HUB_DEBOUNCE_STABLE); 738 delay = HUB_DEBOUNCE_STABLE;
697 739
740 /* Don't do a long sleep inside a workqueue routine */
741 if (type == HUB_INIT2) {
742 PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
743 schedule_delayed_work(&hub->init_work,
744 msecs_to_jiffies(delay));
745 return; /* Continues at init3: below */
746 } else {
747 msleep(delay);
748 }
749 }
750 init3:
698 hub->quiescing = 0; 751 hub->quiescing = 0;
699 752
700 status = usb_submit_urb(hub->urb, GFP_NOIO); 753 status = usb_submit_urb(hub->urb, GFP_NOIO);
@@ -707,6 +760,21 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
707 kick_khubd(hub); 760 kick_khubd(hub);
708} 761}
709 762
763/* Implement the continuations for the delays above */
764static void hub_init_func2(struct work_struct *ws)
765{
766 struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
767
768 hub_activate(hub, HUB_INIT2);
769}
770
771static void hub_init_func3(struct work_struct *ws)
772{
773 struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
774
775 hub_activate(hub, HUB_INIT3);
776}
777
710enum hub_quiescing_type { 778enum hub_quiescing_type {
711 HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND 779 HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
712}; 780};
@@ -716,6 +784,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
716 struct usb_device *hdev = hub->hdev; 784 struct usb_device *hdev = hub->hdev;
717 int i; 785 int i;
718 786
787 cancel_delayed_work_sync(&hub->init_work);
788
719 /* khubd and related activity won't re-trigger */ 789 /* khubd and related activity won't re-trigger */
720 hub->quiescing = 1; 790 hub->quiescing = 1;
721 791
@@ -1099,6 +1169,7 @@ descriptor_error:
1099 hub->intfdev = &intf->dev; 1169 hub->intfdev = &intf->dev;
1100 hub->hdev = hdev; 1170 hub->hdev = hdev;
1101 INIT_DELAYED_WORK(&hub->leds, led_work); 1171 INIT_DELAYED_WORK(&hub->leds, led_work);
1172 INIT_DELAYED_WORK(&hub->init_work, NULL);
1102 usb_get_intf(intf); 1173 usb_get_intf(intf);
1103 1174
1104 usb_set_intfdata (intf, hub); 1175 usb_set_intfdata (intf, hub);
@@ -3035,7 +3106,7 @@ static void hub_events(void)
3035 i); 3106 i);
3036 clear_port_feature(hdev, i, 3107 clear_port_feature(hdev, i,
3037 USB_PORT_FEAT_C_OVER_CURRENT); 3108 USB_PORT_FEAT_C_OVER_CURRENT);
3038 hub_power_on(hub); 3109 hub_power_on(hub, true);
3039 } 3110 }
3040 3111
3041 if (portchange & USB_PORT_STAT_C_RESET) { 3112 if (portchange & USB_PORT_STAT_C_RESET) {
@@ -3070,7 +3141,7 @@ static void hub_events(void)
3070 dev_dbg (hub_dev, "overcurrent change\n"); 3141 dev_dbg (hub_dev, "overcurrent change\n");
3071 msleep(500); /* Cool down */ 3142 msleep(500); /* Cool down */
3072 clear_hub_feature(hdev, C_HUB_OVER_CURRENT); 3143 clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
3073 hub_power_on(hub); 3144 hub_power_on(hub, true);
3074 } 3145 }
3075 } 3146 }
3076 3147