USB: Reset USB 3.0 devices on (re)discovery
authorLuben Tuikov <ltuikov@yahoo.com>
Fri, 11 Feb 2011 19:33:10 +0000 (11:33 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 7 Mar 2011 23:05:14 +0000 (15:05 -0800)
commit8adc60863e6f85a50212d0b8623c38fdb7e5d4c7
tree8f60a3cad159f568745a963b3897720cf444614b
parent929364a96776f45edc9b1d71680bf87852dfc39b
USB: Reset USB 3.0 devices on (re)discovery

commit 07194ab7be63a972096309ab0ea747df455c6a20 upstream.

If the device isn't reset, the XHCI HCD sends
SET ADDRESS to address 0 while the device is
already in Addressed state, and the request is
dropped on the floor as it is addressed to the
default address. This sequence of events, which this
patch fixes looks like this:

usb_reset_and_verify_device()
hub_port_init()
hub_set_address()
SET_ADDRESS to 0 with 1
usb_get_device_descriptor(udev, 8)
usb_get_device_descriptor(udev, 18)
descriptors_changed() --> goto re_enumerate:
hub_port_logical_disconnect()
kick_khubd()

And then:

hub_events()
hub_port_connect_change()
usb_disconnect()
usb_disable_device()
new device struct
sets device state to Powered
choose_address()
hub_port_init() <-- no reset, but SET ADDRESS to 0 with 1, timeout!

The solution is to always reset the device in
hub_port_init() to put it in a known state.

Note from Sarah Sharp:

This patch should be queued for stable trees all the way back to 2.6.34,
since that was the first kernel that supported configured device reset.
The code this patch touches has been there since 2.6.32, but the bug
would never be hit before 2.6.34 because the xHCI driver would
completely reject an attempt to reset a configured device under xHCI.

Signed-off-by: Luben Tuikov <ltuikov@yahoo.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hub.c