aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb27
-rw-r--r--drivers/usb/core/sysfs.c54
-rw-r--r--drivers/usb/host/xhci.c6
-rw-r--r--include/linux/usb.h18
4 files changed, 103 insertions, 2 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index f093e59cbe5f..9759b8c91332 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -236,3 +236,30 @@ Description:
236 This attribute is to expose these information to user space. 236 This attribute is to expose these information to user space.
237 The file will read "hotplug", "wired" and "not used" if the 237 The file will read "hotplug", "wired" and "not used" if the
238 information is available, and "unknown" otherwise. 238 information is available, and "unknown" otherwise.
239
240What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
241Date: May 2013
242Contact: Mathias Nyman <mathias.nyman@linux.intel.com>
243Description:
244 USB 2.0 devices may support hardware link power management (LPM)
245 L1 sleep state. The usb2_lpm_l1_timeout attribute allows
246 tuning the timeout for L1 inactivity timer (LPM timer), e.g.
247 needed inactivity time before host requests the device to go to L1 sleep.
248 Useful for power management tuning.
249 Supported values are 0 - 65535 microseconds.
250
251What: /sys/bus/usb/devices/.../power/usb2_lpm_besl
252Date: May 2013
253Contact: Mathias Nyman <mathias.nyman@linux.intel.com>
254Description:
255 USB 2.0 devices that support hardware link power management (LPM)
256 L1 sleep state now use a best effort service latency value (BESL) to
257 indicate the best effort to resumption of service to the device after the
258 initiation of the resume event.
259 If the device does not have a preferred besl value then the host can select
260 one instead. This usb2_lpm_besl attribute allows to tune the host selected besl
261 value in order to tune power saving and service latency.
262
263 Supported values are 0 - 15.
264 More information on how besl values map to microseconds can be found in
265 USB 2.0 ECN Errata for Link Power Management, section 4.10)
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index aa38db44818a..d9284b998bd7 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -497,8 +497,62 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
497static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, 497static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,
498 set_usb2_hardware_lpm); 498 set_usb2_hardware_lpm);
499 499
500static ssize_t
501show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
502 char *buf)
503{
504 struct usb_device *udev = to_usb_device(dev);
505 return sprintf(buf, "%d\n", udev->l1_params.timeout);
506}
507
508static ssize_t
509set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
510 const char *buf, size_t count)
511{
512 struct usb_device *udev = to_usb_device(dev);
513 u16 timeout;
514
515 if (kstrtou16(buf, 0, &timeout))
516 return -EINVAL;
517
518 udev->l1_params.timeout = timeout;
519
520 return count;
521}
522
523static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR,
524 show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout);
525
526static ssize_t
527show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
528 char *buf)
529{
530 struct usb_device *udev = to_usb_device(dev);
531 return sprintf(buf, "%d\n", udev->l1_params.besl);
532}
533
534static ssize_t
535set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
536 const char *buf, size_t count)
537{
538 struct usb_device *udev = to_usb_device(dev);
539 u8 besl;
540
541 if (kstrtou8(buf, 0, &besl) || besl > 15)
542 return -EINVAL;
543
544 udev->l1_params.besl = besl;
545
546 return count;
547}
548
549static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR,
550 show_usb2_lpm_besl, set_usb2_lpm_besl);
551
500static struct attribute *usb2_hardware_lpm_attr[] = { 552static struct attribute *usb2_hardware_lpm_attr[] = {
501 &dev_attr_usb2_hardware_lpm.attr, 553 &dev_attr_usb2_hardware_lpm.attr,
554 &dev_attr_usb2_lpm_l1_timeout.attr,
555 &dev_attr_usb2_lpm_besl.attr,
502 NULL, 556 NULL,
503}; 557};
504static struct attribute_group usb2_hardware_lpm_attr_group = { 558static struct attribute_group usb2_hardware_lpm_attr_group = {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3d34a0eed088..8be34f838bd4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3917,7 +3917,7 @@ static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev)
3917 field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); 3917 field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
3918 3918
3919 /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ 3919 /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */
3920 l1 = XHCI_L1_TIMEOUT / 256; 3920 l1 = udev->l1_params.timeout / 256;
3921 3921
3922 /* device has preferred BESLD */ 3922 /* device has preferred BESLD */
3923 if (field & USB_BESL_DEEP_VALID) { 3923 if (field & USB_BESL_DEEP_VALID) {
@@ -4101,7 +4101,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
4101 (field & USB_BESL_BASELINE_VALID)) 4101 (field & USB_BESL_BASELINE_VALID))
4102 hird = USB_GET_BESL_BASELINE(field); 4102 hird = USB_GET_BESL_BASELINE(field);
4103 else 4103 else
4104 hird = XHCI_DEFAULT_BESL; 4104 hird = udev->l1_params.besl;
4105 4105
4106 exit_latency = xhci_besl_encoding[hird]; 4106 exit_latency = xhci_besl_encoding[hird];
4107 spin_unlock_irqrestore(&xhci->lock, flags); 4107 spin_unlock_irqrestore(&xhci->lock, flags);
@@ -4191,6 +4191,8 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
4191 if (xhci->hw_lpm_support == 1 && 4191 if (xhci->hw_lpm_support == 1 &&
4192 xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { 4192 xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) {
4193 udev->usb2_hw_lpm_capable = 1; 4193 udev->usb2_hw_lpm_capable = 1;
4194 udev->l1_params.timeout = XHCI_L1_TIMEOUT;
4195 udev->l1_params.besl = XHCI_DEFAULT_BESL;
4194 if (xhci_check_usb2_port_capability(xhci, portnum, 4196 if (xhci_check_usb2_port_capability(xhci, portnum,
4195 XHCI_BLC)) 4197 XHCI_BLC))
4196 udev->usb2_hw_lpm_besl_capable = 1; 4198 udev->usb2_hw_lpm_besl_capable = 1;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index fe444989668a..a232b7ece1f6 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -394,6 +394,22 @@ enum usb_port_connect_type {
394}; 394};
395 395
396/* 396/*
397 * USB 2.0 Link Power Management (LPM) parameters.
398 */
399struct usb2_lpm_parameters {
400 /* Best effort service latency indicate how long the host will drive
401 * resume on an exit from L1.
402 */
403 unsigned int besl;
404
405 /* Timeout value in microseconds for the L1 inactivity (LPM) timer.
406 * When the timer counts to zero, the parent hub will initiate a LPM
407 * transition to L1.
408 */
409 int timeout;
410};
411
412/*
397 * USB 3.0 Link Power Management (LPM) parameters. 413 * USB 3.0 Link Power Management (LPM) parameters.
398 * 414 *
399 * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit. 415 * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit.
@@ -488,6 +504,7 @@ struct usb3_lpm_parameters {
488 * specific data for the device. 504 * specific data for the device.
489 * @slot_id: Slot ID assigned by xHCI 505 * @slot_id: Slot ID assigned by xHCI
490 * @removable: Device can be physically removed from this port 506 * @removable: Device can be physically removed from this port
507 * @l1_params: best effor service latency for USB2 L1 LPM state, and L1 timeout.
491 * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout. 508 * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout.
492 * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout. 509 * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout.
493 * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm() 510 * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm()
@@ -568,6 +585,7 @@ struct usb_device {
568 struct wusb_dev *wusb_dev; 585 struct wusb_dev *wusb_dev;
569 int slot_id; 586 int slot_id;
570 enum usb_device_removable removable; 587 enum usb_device_removable removable;
588 struct usb2_lpm_parameters l1_params;
571 struct usb3_lpm_parameters u1_params; 589 struct usb3_lpm_parameters u1_params;
572 struct usb3_lpm_parameters u2_params; 590 struct usb3_lpm_parameters u2_params;
573 unsigned lpm_disable_count; 591 unsigned lpm_disable_count;