Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: add usb2 Link PM variables to sysfs and usb_device

Adds abitilty to tune L1 timeout (inactivity timer for usb2 link sleep)
and BESL (best effort service latency)via sysfs.

This also adds a new usb2_lpm_parameters structure with those variables to
struct usb_device.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>

authored by

Mathias Nyman and committed by
Sarah Sharp
17f34867 a558ccdc

+103 -2
+27
Documentation/ABI/testing/sysfs-bus-usb
··· 236 236 This attribute is to expose these information to user space. 237 237 The file will read "hotplug", "wired" and "not used" if the 238 238 information is available, and "unknown" otherwise. 239 + 240 + What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout 241 + Date: May 2013 242 + Contact: Mathias Nyman <mathias.nyman@linux.intel.com> 243 + Description: 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 + 251 + What: /sys/bus/usb/devices/.../power/usb2_lpm_besl 252 + Date: May 2013 253 + Contact: Mathias Nyman <mathias.nyman@linux.intel.com> 254 + Description: 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)
+54
drivers/usb/core/sysfs.c
··· 497 497 static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, 498 498 set_usb2_hardware_lpm); 499 499 500 + static ssize_t 501 + show_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 + 508 + static ssize_t 509 + set_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 + 523 + static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR, 524 + show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout); 525 + 526 + static ssize_t 527 + show_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 + 534 + static ssize_t 535 + set_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 + 549 + static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR, 550 + show_usb2_lpm_besl, set_usb2_lpm_besl); 551 + 500 552 static struct attribute *usb2_hardware_lpm_attr[] = { 501 553 &dev_attr_usb2_hardware_lpm.attr, 554 + &dev_attr_usb2_lpm_l1_timeout.attr, 555 + &dev_attr_usb2_lpm_besl.attr, 502 556 NULL, 503 557 }; 504 558 static struct attribute_group usb2_hardware_lpm_attr_group = {
+4 -2
drivers/usb/host/xhci.c
··· 3917 3917 field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); 3918 3918 3919 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 3922 /* device has preferred BESLD */ 3923 3923 if (field & USB_BESL_DEEP_VALID) { ··· 4101 4101 (field & USB_BESL_BASELINE_VALID)) 4102 4102 hird = USB_GET_BESL_BASELINE(field); 4103 4103 else 4104 - hird = XHCI_DEFAULT_BESL; 4104 + hird = udev->l1_params.besl; 4105 4105 4106 4106 exit_latency = xhci_besl_encoding[hird]; 4107 4107 spin_unlock_irqrestore(&xhci->lock, flags); ··· 4191 4191 if (xhci->hw_lpm_support == 1 && 4192 4192 xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { 4193 4193 udev->usb2_hw_lpm_capable = 1; 4194 + udev->l1_params.timeout = XHCI_L1_TIMEOUT; 4195 + udev->l1_params.besl = XHCI_DEFAULT_BESL; 4194 4196 if (xhci_check_usb2_port_capability(xhci, portnum, 4195 4197 XHCI_BLC)) 4196 4198 udev->usb2_hw_lpm_besl_capable = 1;
+18
include/linux/usb.h
··· 394 394 }; 395 395 396 396 /* 397 + * USB 2.0 Link Power Management (LPM) parameters. 398 + */ 399 + struct 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 413 * USB 3.0 Link Power Management (LPM) parameters. 398 414 * 399 415 * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit. ··· 504 488 * specific data for the device. 505 489 * @slot_id: Slot ID assigned by xHCI 506 490 * @removable: Device can be physically removed from this port 491 + * @l1_params: best effor service latency for USB2 L1 LPM state, and L1 timeout. 507 492 * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout. 508 493 * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout. 509 494 * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm() ··· 585 568 struct wusb_dev *wusb_dev; 586 569 int slot_id; 587 570 enum usb_device_removable removable; 571 + struct usb2_lpm_parameters l1_params; 588 572 struct usb3_lpm_parameters u1_params; 589 573 struct usb3_lpm_parameters u2_params; 590 574 unsigned lpm_disable_count;