]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.4.58/usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.58 / usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch
CommitLineData
ac193935
GKH
1From 481f2d4f89f87a0baa26147f323380e31cfa7c44 Mon Sep 17 00:00:00 2001
2From: Julius Werner <jwerner@chromium.org>
3Date: Tue, 30 Jul 2013 19:51:20 -0700
4Subject: usb: core: don't try to reset_device() a port that got just disconnected
5
6From: Julius Werner <jwerner@chromium.org>
7
8commit 481f2d4f89f87a0baa26147f323380e31cfa7c44 upstream.
9
10The USB hub driver's event handler contains a check to catch SuperSpeed
11devices that transitioned into the SS.Inactive state and tries to fix
12them with a reset. It decides whether to do a plain hub port reset or
13call the usb_reset_device() function based on whether there was a device
14attached to the port.
15
16However, there are device/hub combinations (found with a JetFlash
17Transcend mass storage stick (8564:1000) on the root hub of an Intel
18LynxPoint PCH) which can transition to the SS.Inactive state on
19disconnect (and stay there long enough for the host to notice). In this
20case, above-mentioned reset check will call usb_reset_device() on the
21stale device data structure. The kernel will send pointless LPM control
22messages to the no longer connected device address and can even cause
23several 5 second khubd stalls on some (buggy?) host controllers, before
24finally accepting the device's fate amongst a flurry of error messages.
25
26This patch makes the choice of reset dependent on the port status that
27has just been read from the hub in addition to the existence of an
28in-kernel data structure for the device, and only proceeds with the more
29extensive reset if both are valid.
30
31Signed-off-by: Julius Werner <jwerner@chromium.org>
32Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
33Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35---
36 drivers/usb/core/hub.c | 5 +++--
37 1 file changed, 3 insertions(+), 2 deletions(-)
38
39--- a/drivers/usb/core/hub.c
40+++ b/drivers/usb/core/hub.c
41@@ -3890,7 +3890,8 @@ static void hub_events(void)
42 hub->hdev->children[i - 1];
43
44 dev_dbg(hub_dev, "warm reset port %d\n", i);
45- if (!udev) {
46+ if (!udev || !(portstatus &
47+ USB_PORT_STAT_CONNECTION)) {
48 status = hub_port_reset(hub, i,
49 NULL, HUB_BH_RESET_TIME,
50 true);
51@@ -3900,8 +3901,8 @@ static void hub_events(void)
52 usb_lock_device(udev);
53 status = usb_reset_device(udev);
54 usb_unlock_device(udev);
55+ connect_change = 0;
56 }
57- connect_change = 0;
58 }
59
60 if (connect_change)