Skip to content

Commit 890dae8

Browse files
matnymanSarah Sharp
authored andcommitted
xhci: Enable LPM support only for hardwired or BESL devices
Some usb3 devices falsely claim they support usb2 hardware Link PM when connected to a usb2 port. We only trust hardwired devices or devices with the later BESL LPM support to be LPM enabled as default. [Note: Sarah re-worked the original patch to move the code into the USB core, and updated it to check whether the USB device supports BESL, instead of checking if the xHCI port it's connected to supports BESL encoding.] This patch should be backported to kernels as old as 3.11, that contain the commit a558ccd "usb: xhci: add USB2 Link power management BESL support". Without this fix, some USB 3.0 devices will not enumerate or work properly under USB 2.0 ports on Haswell-ULT systems. Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Sarah Sharp <[email protected]> Cc: [email protected]
1 parent de68bab commit 890dae8

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/usb/core/hub.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,6 +3953,32 @@ static int hub_set_address(struct usb_device *udev, int devnum)
39533953
return retval;
39543954
}
39553955

3956+
/*
3957+
* There are reports of USB 3.0 devices that say they support USB 2.0 Link PM
3958+
* when they're plugged into a USB 2.0 port, but they don't work when LPM is
3959+
* enabled.
3960+
*
3961+
* Only enable USB 2.0 Link PM if the port is internal (hardwired), or the
3962+
* device says it supports the new USB 2.0 Link PM errata by setting the BESL
3963+
* support bit in the BOS descriptor.
3964+
*/
3965+
static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
3966+
{
3967+
int connect_type;
3968+
3969+
if (!udev->usb2_hw_lpm_capable)
3970+
return;
3971+
3972+
connect_type = usb_get_hub_port_connect_type(udev->parent,
3973+
udev->portnum);
3974+
3975+
if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) ||
3976+
connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
3977+
udev->usb2_hw_lpm_allowed = 1;
3978+
usb_set_usb2_hardware_lpm(udev, 1);
3979+
}
3980+
}
3981+
39563982
/* Reset device, (re)assign address, get device descriptor.
39573983
* Device connection must be stable, no more debouncing needed.
39583984
* Returns device in USB_STATE_ADDRESS, except on error.
@@ -4246,6 +4272,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
42464272
/* notify HCD that we have a device connected and addressed */
42474273
if (hcd->driver->update_device)
42484274
hcd->driver->update_device(hcd, udev);
4275+
hub_set_initial_usb2_lpm_policy(udev);
42494276
fail:
42504277
if (retval) {
42514278
hub_port_disable(hub, port1, 0);

0 commit comments

Comments
 (0)