On Wed, Oct 03, 2012 at 11:29:00AM -0700, Sarah Sharp wrote: > Hi Don, > > Please test this patch on top of the other patch. So yeah, that seemed to work. :-) Thanks! Cheers, Don > > Sarah Sharp > > >8-------------------------------------------------------------------8< > 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. > > Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> > Reported-by: Don Zickus <dzickus@xxxxxxxxxx> > --- > drivers/usb/core/hub.c | 14 ++++++++++---- > 1 files changed, 10 insertions(+), 4 deletions(-) > > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index 55bef91..2568441 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -3484,8 +3484,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; > - __le16 u2_mel; > + __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 > @@ -3512,8 +3520,6 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, > * 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)) { > -- > 1.7.9 > -- 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