summaryrefslogtreecommitdiff
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorLu Baolu <baolu.lu@linux.intel.com>2015-11-14 16:26:33 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-01 14:58:18 -0800
commit513072d90a8dfe4bf83e1f81810de605eb5d7c3b (patch)
tree101e668a61262a515b2ab8124f2d9ba568df7432 /drivers/usb/core/hub.c
parentbf5ce5bf3cc7136fd7fe5e8999a580bc93a9c8f6 (diff)
usb: core: lpm: add sysfs node for usb3 lpm permit
USB3 LPM is default on in Linux kernel if both xHCI host controller and the USB devices declare to be LPM-capable. Unfortunately, some devices are known to work well with LPM disabled, but to be broken if LPM is enabled, although it declares the LPM capability. Users won't be able to use this kind of devices, until someone puts them in the kernel blacklist and gets the kernel upgraded. This patch adds a sysfs node to permit or forbit USB3 LPM U1 or U2 entry for a port. The settings apply to both before and after device enumeration. Supported values are "0" - neither u1 nor u2 permitted, "u1" - only u1 is permitted, "u2" - only u2 is permitted, "u1_u2" - both u1 and u2 are permitted. With this interface, users can use an LPM-unfriendly USB device on a released Linux kernel. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Zhuang Jin Can <jin.can.zhuang@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 59f998e60030..db7683e2d34c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4020,6 +4020,8 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);
void usb_enable_lpm(struct usb_device *udev)
{
struct usb_hcd *hcd;
+ struct usb_hub *hub;
+ struct usb_port *port_dev;
if (!udev || !udev->parent ||
udev->speed != USB_SPEED_SUPER ||
@@ -4039,8 +4041,17 @@ void usb_enable_lpm(struct usb_device *udev)
if (udev->lpm_disable_count > 0)
return;
- usb_enable_link_state(hcd, udev, USB3_LPM_U1);
- usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+ hub = usb_hub_to_struct_hub(udev->parent);
+ if (!hub)
+ return;
+
+ port_dev = hub->ports[udev->portnum - 1];
+
+ if (port_dev->usb3_lpm_u1_permit)
+ usb_enable_link_state(hcd, udev, USB3_LPM_U1);
+
+ if (port_dev->usb3_lpm_u2_permit)
+ usb_enable_link_state(hcd, udev, USB3_LPM_U2);
}
EXPORT_SYMBOL_GPL(usb_enable_lpm);