diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-10-03 11:18:05 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-28 10:56:14 -0700 |
commit | 6a154bb60bfcbc91b515a94ee68e35c3b4b01b7c (patch) | |
tree | e7da10323fdb7b40970581bbade2bba649ac6992 | |
parent | 740b0a623f05bbb796a441e2c51ebfe37eef1c21 (diff) | |
download | linux-stable-6a154bb60bfcbc91b515a94ee68e35c3b4b01b7c.tar.gz linux-stable-6a154bb60bfcbc91b515a94ee68e35c3b4b01b7c.tar.bz2 linux-stable-6a154bb60bfcbc91b515a94ee68e35c3b4b01b7c.zip |
usb: Don't enable LPM if the exit latency is zero.
commit ae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f upstream.
Some USB 3.0 devices signal that they don't implement Link PM by having
all zeroes in the U1/U2 exit latencies in their SuperSpeed BOS
descriptor. Don found that a Western Digital device he has experiences
transfer errors when LPM is enabled. The lsusb shows the U1/U2 exit
latencies are set to zero:
Binary Object Store Descriptor:
bLength 5
bDescriptorType 15
wTotalLength 22
bNumDeviceCaps 2
SuperSpeed USB Device Capability:
bLength 10
bDescriptorType 16
bDevCapabilityType 3
bmAttributes 0x00
Latency Tolerance Messages (LTM) Supported
wSpeedsSupported 0x000e
Device can operate at Full Speed (12Mbps)
Device can operate at High Speed (480Mbps)
Device can operate at SuperSpeed (5Gbps)
bFunctionalitySupport 1
Lowest fully-functional device speed is Full Speed (12Mbps)
bU1DevExitLat 0 micro seconds
bU2DevExitLat 0 micro seconds
The fix is to not enable LPM for a particular link state if we find its
corresponding exit latency is zero.
This patch should be backported to kernels as old as 3.5, that contain
the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to
enable/disable USB3 link states."
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Reported-by: Don Zickus <dzickus@redhat.com>
Tested-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/core/hub.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 128a804c42f4..d1a43ab01167 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3353,6 +3353,16 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { int timeout; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the |