Hi Don, The WD drive arrived today, but I can't reproduce your I/O errors on 3.6. I didn't try with 3.5 yet. However, I did notice that the device really doesn't want to enter U1, but it will enter U2. Can you test the following patch with your device and see if it helps? If that doesn't work, I suggest getting a high-quality new cable and seeing if that helps the transfer issues. Gabor, this might fix your issues as well, and should allow your system to consume less power than completely disabling LPM. Sarah Sharp >8-------------------------------------------------------------8< USB 3.0 devices are required to support Link PM. However, some of them don't support U1, or don't support U2, or don't support either. There is no way in the USB 3.0 specification to say that a device doesn't support U1 or U2, so these devices set the U1 or U2 exit latency to the maximum possible values (10ms for U1, 2047ms for U2). With the old code, when we enabled hub-initiated U1 or U2 for a device on the roothub, the host would send LGO_U1 and LGO_U2 every 10ms or 2047ms, respectively. The device would always send refuse to go into the lower power link state, and would send an LAUX back. The constant U1/U2 refusals would fill an idle bus with link commands. This caused transfer errors and timeouts with a Western Digital My Passport Essential 500 GB USB 3.0 hard drive (PID:VID 1058:0740). The lsusb shows that device has the maximum possible device exit latency for U1, but has a non-max U2 exit latency: 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 10 micro seconds bU2DevExitLat 32 micro seconds Change the LPM enabling code to look for the maximum U1 and U2 exit latencies. If we find those magic values, don't enable hub-initiated transitions to U1 or U2. Instead, let the device initiate the lower power link state. That way, if a device does support U1 or U2 and it truely needs the maximum exit latency, we can still save power. With this patch, the roothub lsusb output shows the device is happy to go into U2, just not U1: Hub Port Status: Port 1: 0000.0243 5Gbps power U2 enable connect Port 2: 0000.0263 5Gbps power suspend enable connect Port 3: 0000.02a0 5Gbps power Rx.Detect Port 4: 0000.02a0 5Gbps power Rx.Detect This patch should be backported to stable 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@xxxxxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx --- drivers/usb/core/hub.c | 19 +++++++++++++++++++ include/linux/usb/ch9.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 128a804..e1065ed 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3353,6 +3353,8 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { int timeout; + __u8 u1_mel; + __le16 u2_mel; /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the @@ -3372,6 +3374,23 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, return; } + /* + * Magic maximum device exit latency values may mean the device doesn't + * support U1 or U2. If hub-initiated LPM is enabled, the device will + * always refuse to go into U1 or U2, and will fill the bus with LAUX + * link commands. This can cause transfer errors, so only enable + * device-initiated LPM. + */ + u1_mel = udev->bos->ss_cap->bU1devExitLat; + u2_mel = udev->bos->ss_cap->bU2DevExitLat; + if ((state == USB3_LPM_U1 && u1_mel == USB_U1_MAX_VALID_MEL) || + (state == USB3_LPM_U2 && + le16_to_cpu(u2_mel) == USB_U2_MAX_VALID_MEL)) { + if (usb_set_device_initiated_lpm(udev, state, true)) + hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); + return; + } + if (usb_set_lpm_timeout(udev, state, timeout)) /* If we can't set the parent hub U1/U2 timeout, * device-initiated LPM won't be allowed either, so let the xHCI diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index d1d732c..edf28ac 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -828,7 +828,9 @@ struct usb_ss_cap_descriptor { /* Link Power Management */ #define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */ #define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */ __u8 bFunctionalitySupport; +#define USB_U1_MAX_VALID_MEL 0x0A /* U1 MEL is 10us, max */ __u8 bU1devExitLat; +#define USB_U2_MAX_VALID_MEL 0x7FF /* U2 MEL is 2047us, max */ __le16 bU2DevExitLat; } __attribute__((packed)); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html