aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-04-28 11:07:07 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-21 18:15:52 -0400
commit948fea37dcebfef8f0f2faf00930e7ec7e756e07 (patch)
treeaa75e31943da805bb613f7738276e352ec10cea0 /drivers
parent8808f00c7adfc8dc0b797c34ec03490b237fce4e (diff)
USB: optimize port debouncing during hub activation
This patch (as1082) makes a small optimization to the way the hub driver carries out port debouncing immediately after a hub is activated (i.e., initialized, reset, or resumed). If any port-change statuses are observed, the code will delay for a minimal debounce period -- thereby making a good start at debouncing all the ports at once. If this wasn't sufficient then khubd will debounce any port that still requires attention. But in most cases it should suffice; it's rare for a device to need more than a minimal debounce delay. (In the cases of hub initialization or reset even that is most likely not needed, since any devices plugged in at such times have probably been attached for a while.) Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/hub.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8ea095e59099..bc80168957b8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -130,6 +130,10 @@ MODULE_PARM_DESC(use_both_schemes,
130DECLARE_RWSEM(ehci_cf_port_reset_rwsem); 130DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
131EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); 131EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
132 132
133#define HUB_DEBOUNCE_TIMEOUT 1500
134#define HUB_DEBOUNCE_STEP 25
135#define HUB_DEBOUNCE_STABLE 100
136
133 137
134static inline char *portspeed(int portstatus) 138static inline char *portspeed(int portstatus)
135{ 139{
@@ -643,6 +647,7 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
643{ 647{
644 struct usb_device *hdev = hub->hdev; 648 struct usb_device *hdev = hub->hdev;
645 int port1; 649 int port1;
650 bool need_debounce_delay = false;
646 651
647 /* Check each port and set hub->change_bits to let khubd know 652 /* Check each port and set hub->change_bits to let khubd know
648 * which ports need attention. 653 * which ports need attention.
@@ -673,6 +678,18 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
673 portstatus &= ~USB_PORT_STAT_ENABLE; 678 portstatus &= ~USB_PORT_STAT_ENABLE;
674 } 679 }
675 680
681 /* Clear status-change flags; we'll debounce later */
682 if (portchange & USB_PORT_STAT_C_CONNECTION) {
683 need_debounce_delay = true;
684 clear_port_feature(hub->hdev, port1,
685 USB_PORT_FEAT_C_CONNECTION);
686 }
687 if (portchange & USB_PORT_STAT_C_ENABLE) {
688 need_debounce_delay = true;
689 clear_port_feature(hub->hdev, port1,
690 USB_PORT_FEAT_C_ENABLE);
691 }
692
676 if (!udev || udev->state == USB_STATE_NOTATTACHED) { 693 if (!udev || udev->state == USB_STATE_NOTATTACHED) {
677 /* Tell khubd to disconnect the device or 694 /* Tell khubd to disconnect the device or
678 * check for a new connection 695 * check for a new connection
@@ -702,6 +719,16 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
702 } 719 }
703 } 720 }
704 721
722 /* If no port-status-change flags were set, we don't need any
723 * debouncing. If flags were set we can try to debounce the
724 * ports all at once right now, instead of letting khubd do them
725 * one at a time later on.
726 *
727 * If any port-status changes do occur during this delay, khubd
728 * will see them later and handle them normally.
729 */
730 if (need_debounce_delay)
731 msleep(HUB_DEBOUNCE_STABLE);
705 hub_activate(hub); 732 hub_activate(hub);
706} 733}
707 734
@@ -2211,11 +2238,6 @@ static inline int remote_wakeup(struct usb_device *udev)
2211 * every 25ms for transient disconnects. When the port status has been 2238 * every 25ms for transient disconnects. When the port status has been
2212 * unchanged for 100ms it returns the port status. 2239 * unchanged for 100ms it returns the port status.
2213 */ 2240 */
2214
2215#define HUB_DEBOUNCE_TIMEOUT 1500
2216#define HUB_DEBOUNCE_STEP 25
2217#define HUB_DEBOUNCE_STABLE 100
2218
2219static int hub_port_debounce(struct usb_hub *hub, int port1) 2241static int hub_port_debounce(struct usb_hub *hub, int port1)
2220{ 2242{
2221 int ret; 2243 int ret;