diff options
author | Mathias Nyman <mathias.nyman@linux.intel.com> | 2013-05-23 17:14:31 +0300 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2013-06-05 16:48:40 -0700 |
commit | 17f34867e98d2fb0c03918faab79efb989fa134b (patch) | |
tree | 1ea3f266473f6d6aa7fec9a646e04158941d0a06 /drivers | |
parent | a558ccdcc71c7770c5e80c926a31cfe8a3892a09 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/sysfs.c | 54 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 6 |
2 files changed, 58 insertions, 2 deletions
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, static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, set_usb2_hardware_lpm); +static ssize_t +show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_device *udev = to_usb_device(dev); + return sprintf(buf, "%d\n", udev->l1_params.timeout); +} + +static ssize_t +set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_device *udev = to_usb_device(dev); + u16 timeout; + + if (kstrtou16(buf, 0, &timeout)) + return -EINVAL; + + udev->l1_params.timeout = timeout; + + return count; +} + +static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR, + show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout); + +static ssize_t +show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_device *udev = to_usb_device(dev); + return sprintf(buf, "%d\n", udev->l1_params.besl); +} + +static ssize_t +set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_device *udev = to_usb_device(dev); + u8 besl; + + if (kstrtou8(buf, 0, &besl) || besl > 15) + return -EINVAL; + + udev->l1_params.besl = besl; + + return count; +} + +static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR, + show_usb2_lpm_besl, set_usb2_lpm_besl); + static struct attribute *usb2_hardware_lpm_attr[] = { &dev_attr_usb2_hardware_lpm.attr, + &dev_attr_usb2_lpm_l1_timeout.attr, + &dev_attr_usb2_lpm_besl.attr, NULL, }; static 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) field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ - l1 = XHCI_L1_TIMEOUT / 256; + l1 = udev->l1_params.timeout / 256; /* device has preferred BESLD */ if (field & USB_BESL_DEEP_VALID) { @@ -4101,7 +4101,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, (field & USB_BESL_BASELINE_VALID)) hird = USB_GET_BESL_BASELINE(field); else - hird = XHCI_DEFAULT_BESL; + hird = udev->l1_params.besl; exit_latency = xhci_besl_encoding[hird]; spin_unlock_irqrestore(&xhci->lock, flags); @@ -4191,6 +4191,8 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) if (xhci->hw_lpm_support == 1 && xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { udev->usb2_hw_lpm_capable = 1; + udev->l1_params.timeout = XHCI_L1_TIMEOUT; + udev->l1_params.besl = XHCI_DEFAULT_BESL; if (xhci_check_usb2_port_capability(xhci, portnum, XHCI_BLC)) udev->usb2_hw_lpm_besl_capable = 1; |