
On Tue, Mar 15, 2016 at 8:59 PM, Stefan Roese sr@denx.de wrote:
This patch changes the USB port scanning procedure and timeout handling in the following ways:
a) The power-on delay in usb_hub_power_on() is now reduced to a value of max(100ms, "hub->desc.bPwrOn2PwrGood * 2"). The code does not wait using mdelay, instead usb_hub_power_on() will wait before querying the device in the scanning loop later. The total timeout for this hub, which is 1 second + "hub->desc.bPwrOn2PwrGood * 2" is calculated and will be used in the following per-port scanning loop as the timeout to detect active USB devices on this hub.
b) Don't delay the minimum delay (for power to stabilize) in usb_hub_power_on(). Instead skip querying these devices in the scannig loop until the delay time is reached.
c) The ports are now scanned in a quasi parallel way. The current code did wait for each (unconnected) port to reach its timeout and only then continue with the next port. This patch now changes this to scan all ports of all USB hubs quasi simultaneously. For this, all ports are added to a scanning list. This list is scanned until all ports are ready by either a) reaching the connection timeout (calculated earlier), or by b) detecting a USB device. This results in a faster USB scan time as the recursive scanning of USB hubs connected to the hub that's currently being scanned will start earlier.
One small functional change to the original code is, that ports with overcurrent detection will now get rescanned multiple times (PORT_OVERCURRENT_MAX_SCAN_COUNT).
Without this patch: starting USB... USB0: USB EHCI 1.00 scanning bus 0 for devices... 9 USB Device(s) found
time: 20.163 seconds
With this patch: starting USB... USB0: USB EHCI 1.00 scanning bus 0 for devices... 9 USB Device(s) found
time: 1.822 seconds
So ~18.3 seconds of USB scanning time reduction.
Signed-off-by: Stefan Roese sr@denx.de Acked-by: Hans de Goede hdegoede@redhat.com Tested-by: Stephen Warren swarren@nvidia.com
Changes in v5:
- Removed superfluous debug output from usb_scan_port()
- Replaced usb_hub_power_on() with usb_set_port_feature() in case of overcurrent detection. This is whats really needed here.
- Added a per-port overcurrent counter and stop re-scanning of a device that exceeds the PORT_OVERCURRENT_MAX_SCAN_COUNT
- Moved list_del() to end of loop in usb_scan_port()
- Moved timeout / delay variables from USB dev to hub struct as they are hub specific
- Moved state_get_skip_delays() to usb_hub_power_on() so that the timeouts are not set there
Changes in v4:
- Moved check for query_delay into usb_scan_port() as suggested by Hans
- Correct list handling (drop INIT_LIST_HEAD)
- Added some missing free() calls
- Changed connect_timeout calculation as suggested by Stephen
- Moved usb_scan_list to other globals to be cleaned up in a later patch
- Added timeout check for non-functional ports (usb_get_port_status return error
- Reverted if logic in loop to remove an indentation level
- Moved debug() output
- Removed unnecessary if when already connected
- Added Hans's Acked-by
- Added Stephen's Tested-by
- Minor rewording / fixes of the commit text
Changes in v3:
- Introduced scanning list containing all USB devices of one USB controller that need to get scanned
- Don't delay in usb_hub_power_on(). Instead skip querying these devices until the delay time is reached.
Changes in v2:
- Remove static USB port configuration patch (for now)
common/usb_hub.c | 317 ++++++++++++++++++++++++++++++++++++++----------------- include/usb.h | 4 + 2 files changed, 227 insertions(+), 94 deletions(-)
Tested-by: Bin Meng bmeng.cn@gmail.com