[RFC PATCH v3 4/4] usb: add usb2 Link PM variables to sysfs and usb_device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxx>
---
 Documentation/ABI/testing/sysfs-bus-usb |   27 +++++++++++++++
 drivers/usb/core/sysfs.c                |   54 +++++++++++++++++++++++++++++++
 drivers/usb/host/xhci.c                 |    6 ++-
 include/linux/usb.h                     |   18 ++++++++++
 4 files changed, 103 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index f093e59..9759b8c 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -236,3 +236,30 @@ Description:
 		This attribute is to expose these information to user space.
 		The file will read "hotplug", "wired" and "not used" if the
 		information is available, and "unknown" otherwise.
+
+What:		/sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
+Date:		May 2013
+Contact:	Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
+Description:
+		USB 2.0 devices may support hardware link power management (LPM)
+		L1 sleep state. The usb2_lpm_l1_timeout attribute allows
+		tuning the timeout for L1 inactivity timer (LPM timer), e.g.
+		needed inactivity time before host requests the device to go to L1 sleep.
+		Useful for power management tuning.
+		Supported values are 0 - 65535 microseconds.
+
+What:		/sys/bus/usb/devices/.../power/usb2_lpm_besl
+Date:		May 2013
+Contact:	Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
+Description:
+		USB 2.0 devices that support hardware link power management (LPM)
+		L1 sleep state now use a best effort service latency value (BESL) to
+		indicate the best effort to resumption of service to the device after the
+		initiation of the resume event.
+		If the device does not have a preferred besl value then the host can select
+		one instead. This usb2_lpm_besl attribute allows to tune the host selected besl
+		value in order to tune power saving and service latency.
+
+		Supported values are 0 - 15.
+		More information on how besl values map to microseconds can be found in
+		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 aa38db4..d9284b9 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 d1eb393..ba7822f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3907,7 +3907,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) {
@@ -4091,7 +4091,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);
@@ -4181,6 +4181,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;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 3a1b864..1f7d63f 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -394,6 +394,22 @@ enum usb_port_connect_type {
 };
 
 /*
+ * USB 2.0 Link Power Management (LPM) parameters.
+ */
+struct usb2_lpm_parameters {
+	/* Best effort service latency indicate how long the host will drive
+	 * resume on an exit from L1.
+	 */
+	unsigned int besl;
+
+	/* Timeout value in microseconds for the L1 inactivity (LPM) timer.
+	 * When the timer counts to zero, the parent hub will initiate a LPM
+	 * transition to L1.
+	 */
+	int timeout;
+};
+
+/*
  * USB 3.0 Link Power Management (LPM) parameters.
  *
  * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit.
@@ -488,6 +504,7 @@ struct usb3_lpm_parameters {
  *	specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
  * @removable: Device can be physically removed from this port
+ * @l1_params: best effor service latency for USB2 L1 LPM state, and L1 timeout.
  * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout.
  * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout.
  * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm()
@@ -568,6 +585,7 @@ struct usb_device {
 	struct wusb_dev *wusb_dev;
 	int slot_id;
 	enum usb_device_removable removable;
+	struct usb2_lpm_parameters l1_params;
 	struct usb3_lpm_parameters u1_params;
 	struct usb3_lpm_parameters u2_params;
 	unsigned lpm_disable_count;
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux