summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorPrimoz Fiser <primoz.fiser@norik.com>2019-10-01 10:17:58 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-10-02 08:58:10 +0200
commit3cb8f32cf5b27edf41b21f1733c8443d06826c50 (patch)
tree2ff2872581ea4d99401d580348dc4faec09cba6e /drivers/usb
parentcac03a8735bf1e73b2b703b9478b1813fa354487 (diff)
downloadbarebox-3cb8f32cf5b27edf41b21f1733c8443d06826c50.tar.gz
barebox-3cb8f32cf5b27edf41b21f1733c8443d06826c50.tar.xz
usb: hub_port_reset(): Speedup hub reset handling
Start with a short USB hub reset delay of 20ms. This can be enough for some configurations. Switch to longer reset delay only if the short delay hasn't been long enough. This USB hub reset handling strategy is also used in the Linux kernel USB hub driver, function hub_port_reset(). Without patch: $ time usb usb: USB: scanning bus for devices... usb: 17 USB Device(s) found time: 21750ms With patch: $ time usb usb: USB: scanning bus for devices... usb: 17 USB Device(s) found time: 16355ms Delta: ~5.5 seconds Signed-off-by: Primoz Fiser <primoz.fiser@norik.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hub.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d01a016077..91604e1ef5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -30,6 +30,9 @@
#define USB_BUFSIZ 512
+#define HUB_SHORT_RESET_TIME 20
+#define HUB_LONG_RESET_TIME 200
+
static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
@@ -116,12 +119,13 @@ int hub_port_reset(struct usb_device *hub, int port, struct usb_device *usb)
int tries;
struct usb_port_status portsts;
unsigned short portstatus, portchange;
+ int delay = HUB_SHORT_RESET_TIME; /* start with short reset delay */
dev_dbg(&hub->dev, "hub_port_reset: resetting port %d...\n", port);
for (tries = 0; tries < MAX_TRIES; tries++) {
usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
- mdelay(200);
+ mdelay(delay);
if (usb_get_port_status(hub, port + 1, &portsts) < 0) {
dev_dbg(&hub->dev, "get_port_status failed status %lX\n",
@@ -148,7 +152,8 @@ int hub_port_reset(struct usb_device *hub, int port, struct usb_device *usb)
if (portstatus & USB_PORT_STAT_ENABLE)
break;
- mdelay(200);
+ /* Switch to long reset delay for the next round */
+ delay = HUB_LONG_RESET_TIME;
}
if (tries == MAX_TRIES) {