aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2013-09-30 10:26:31 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2013-10-16 15:24:20 -0400
commit890dae88672175f1d39f6105444d9bdc71c89258 (patch)
tree12e22d8a15ad64007b16ff46d94dabb21e9297da /drivers/usb/core/hub.c
parentde68bab4fa96014cfaa6fcbcdb9750e32969fb86 (diff)
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 a558ccdcc71c7770c5e80c926a31cfe8a3892a09 "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 <mathias.nyman@linux.intel.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 9be1a2d5fba6..566ac5531407 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3953,6 +3953,32 @@ static int hub_set_address(struct usb_device *udev, int devnum)
3953 return retval; 3953 return retval;
3954} 3954}
3955 3955
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 */
3965static 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
3956/* Reset device, (re)assign address, get device descriptor. 3982/* Reset device, (re)assign address, get device descriptor.
3957 * Device connection must be stable, no more debouncing needed. 3983 * Device connection must be stable, no more debouncing needed.
3958 * Returns device in USB_STATE_ADDRESS, except on error. 3984 * 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,
4246 /* notify HCD that we have a device connected and addressed */ 4272 /* notify HCD that we have a device connected and addressed */
4247 if (hcd->driver->update_device) 4273 if (hcd->driver->update_device)
4248 hcd->driver->update_device(hcd, udev); 4274 hcd->driver->update_device(hcd, udev);
4275 hub_set_initial_usb2_lpm_policy(udev);
4249fail: 4276fail:
4250 if (retval) { 4277 if (retval) {
4251 hub_port_disable(hub, port1, 0); 4278 hub_port_disable(hub, port1, 0);