WSL2-Linux-Kernel/drivers/usb/core
Sarah Sharp a24a607875 USB: Rip out recursive call on warm port reset.
When a hot reset fails on a USB 3.0 port, the current port reset code
recursively calls hub_port_reset inside hub_port_wait_reset.  This isn't
ideal, since we should avoid recursive calls in the kernel, and it also
doesn't allow us to issue multiple warm resets on reset failures.

Rip out the recursive call.  Instead, add code to hub_port_reset to
issue a warm reset if the hot reset fails, and try multiple warm resets
before giving up on the port.

In hub_port_wait_reset, remove the recursive call and re-indent.  The
code is basically the same, except:

1. It bails out early if the port has transitioned to Inactive or
Compliance Mode after the reset completed.

2. It doesn't consider a connect status change to be a failed reset.  If
multiple warm resets needed to be issued, the connect status may have
changed, so we need to ignore that and look at the port link state
instead.  hub_port_reset will now do that.

3. It unconditionally sets udev->speed on all types of successful
resets.  The old recursive code would set the port speed when the second
hub_port_reset returned.

The old code did not handle connected devices needing a warm reset well.
There were only two situations that the old code handled correctly: an
empty port needing a warm reset, and a hot reset that migrated to a warm
reset.

When an empty port needed a warm reset, hub_port_reset was called with
the warm variable set.  The code in hub_port_finish_reset would skip
telling the USB core and the xHC host that the device was reset, because
otherwise that would result in a NULL pointer dereference.

When a USB 3.0 device reset migrated to a warm reset, the recursive call
made the call stack look like this:

hub_port_reset(warm = false)
        hub_wait_port_reset(warm = false)
                hub_port_reset(warm = true)
                        hub_wait_port_reset(warm = true)
                        hub_port_finish_reset(warm = true)
                        (return up the call stack to the first wait)

        hub_port_finish_reset(warm = false)

The old code didn't want to notify the USB core or the xHC host of device reset
twice, so it only did it in the second call to hub_port_finish_reset,
when warm was set to false.  This was necessary because
before patch two ("USB: Ignore xHCI Reset Device status."), the USB core
would pay attention to the xHC Reset Device command error status, and
the second call would always fail.

Now that we no longer have the recursive call, and warm can change from
false to true in hub_port_reset, we need to have hub_port_finish_reset
unconditionally notify the USB core and the xHC of the device reset.

In hub_port_finish_reset, unconditionally clear the connect status
change (CSC) bit for USB 3.0 hubs when the port reset is done.  If we
had to issue multiple warm resets for a device, that bit may have been
set if the device went into SS.Inactive and then was successfully warm
reset.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
2013-01-03 14:10:33 -08:00
..
Kconfig USB: remove CONFIG_EXPERIMENTAL dependancies 2012-09-17 23:00:15 -07:00
Makefile usb: Bind devices to ACPI devices when possible 2012-05-11 17:06:13 -07:00
buffer.c USB: Core: Fix minor coding style issues 2011-01-22 19:35:39 -08:00
config.c usb: Fail a get config when the port is powered off. 2012-09-10 13:04:01 -07:00
devices.c USB: hub_for_each_child should skip unconnected ports 2012-10-24 14:51:21 -07:00
devio.c usbdevfs: Fix broken scatter-gather transfer 2012-10-17 13:41:34 -07:00
driver.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2012-12-13 12:00:02 -08:00
endpoint.c usb/endpoint: Set release callback in the struct device_type instead of in the device itself directly 2012-08-20 14:38:08 -07:00
file.c USB: rename the usb misc class from "usb" to "usbmisc" 2012-06-13 15:37:13 -07:00
generic.c USB: fix authorization and claimed port logic 2012-11-15 16:56:22 -08:00
hcd-pci.c USB: add NO_D3_DURING_SLEEP flag and revert 151b612847 2012-06-13 13:11:39 -07:00
hcd.c Merge 3.7-rc6 into usb-next. 2012-11-16 18:46:21 -08:00
hub.c USB: Rip out recursive call on warm port reset. 2013-01-03 14:10:33 -08:00
message.c USB: core: Free the allocated memory before exiting on error 2012-11-21 13:32:26 -08:00
notify.c usb: Add export.h for EXPORT_SYMBOL/THIS_MODULE where needed 2011-10-31 19:31:25 -04:00
otg_whitelist.h USB: fix codingstyle issues in drivers/usb/core/*.h 2008-02-01 14:35:07 -08:00
quirks.c Merge 3.6-rc6 into usb-next 2012-09-16 20:42:46 -07:00
sysfs.c usb: convert USB_QUIRK_RESET_MORPHS to USB_QUIRK_RESET 2012-08-20 14:38:08 -07:00
urb.c USB: report submission of active URBs 2012-11-11 18:10:46 -08:00
usb-acpi.c Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux 2012-10-08 07:14:06 +09:00
usb.c usb-core: remove CONFIG_HOTPLUG ifdefs 2012-11-21 13:27:16 -08:00
usb.h usb/acpi: Store info on device removability. 2012-09-10 13:04:01 -07:00