[PATCH v4] xhci-hub: Roothub USB2.0 descriptor for BESL DBESL

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

 



Modified the xHCI roothub descriptor to return USB2.0 extension
descriptor Best Effort Service Latency (BESL) and Deep Best Effort
Service Latency (DBESL) values when set on the xHCI host.

On link power management the BESL and DBESL values are used to
estimate L1 exit latency for USB2.0 host and devices. Tools such as
PowerTop and lsusb will use BESL and DBESL values to
monitor LPM L1 exit latency.  Additionally, by presenting the host
controller BESL and DBESL values one could check if the BIOS or
firmware is setting these values correctly.

Currently the root hub device descriptor bcdUSB value is set to zero
by the BIOS. Therefore to test this functionality with lsusb, I hard
coded the usb2_rh_dev_descriptor (not include on patch) to:
        bcdUSB 0x01.

Here is the tested output using lsusb.
$ sudo lsusb -s 01:01 -v
    ...
     Binary Object Store Descriptor:
         bLength                 5
         bDescriptorType        15
         wTotalLength           12
         bNumDeviceCaps          1
         USB 2.0 Extension Device Capability:
           bLength                 7
           bDescriptorType        16
           bDevCapabilityType      2
           bmAttributes   0x0000ff1e
             BESL Link Power Management (LPM) Supported
                BESL value     3840 us
             Deep BESL value    61440 us
        Device Status:     0x0001
          Self Powered
Signed-off-by: Alexandra Yates <alexandra.yates@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-hub.c |   53 +++++++++++++++++++++++++++++++++++++++----
 drivers/usb/host/xhci.h     |    3 +++
 2 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1d35459..0625ad3 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -30,7 +30,7 @@
 			 PORT_RC | PORT_PLC | PORT_PE)
 
 /* USB 3.0 BOS descriptor and a capability descriptor, combined */
-static u8 usb_bos_descriptor [] = {
+static u8 usb3_bos_descriptor[] = {
 	USB_DT_BOS_SIZE,		/*  __u8 bLength, 5 bytes */
 	USB_DT_BOS,			/*  __u8 bDescriptorType */
 	0x0F, 0x00,			/*  __le16 wTotalLength, 15 bytes */
@@ -47,6 +47,28 @@ static u8 usb_bos_descriptor [] = {
 	0x00, 0x00			/* __le16 bU2DevExitLat, set later. */
 };
 
+/* USB 2.0 BOS descriptor and a capability descriptor, combined */
+static u8 usb2_bos_descriptor[] = {
+	USB_DT_BOS_SIZE,                /*  __u8 bLength, 5 bytes */
+	USB_DT_BOS,                     /*  __u8 bDescriptorType */
+	0x0c, 0x00,                     /*  __le16 wTotalLength, 15 bytes */
+	0x1,                            /*  __u8 bNumDeviceCaps */
+					/* First device capability */
+	USB_DT_USB_EXT_CAP_SIZE,        /*  7 bits USB2 ext */
+	USB_DT_DEVICE_CAPABILITY,       /* Device Capability */
+	USB_CAP_TYPE_EXT,               /* DevCapability Type, USB2.0 ext */
+	0x1e,                           /* bmAttributes first byte: bit1:LPM
+					   Supported, bit2: BESL supported,
+					   bit3:valid  baseline BESL, bit4:
+					   valid Deep BESL, bits5-7 */
+	0xff,                           /* bmAttributes - second byte:
+					   8-11bit:BESL and 12-16bit:DBESL*/
+	0x00,                           /* bmAttribute - third byte: reserved,
+					   must be zero */
+	0x00,                           /* bmAttribute - fourth byte: reserved,
+					   must be zero */
+};
+
 
 static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
 		struct usb_hub_descriptor *desc, int ports)
@@ -577,12 +599,33 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		if ((wValue & 0xff00) != (USB_DT_BOS << 8))
 			goto error;
 
-		if (hcd->speed != HCD_USB3)
+		if (hcd->speed == HCD_USB3) {
+			/* Set the U1 and U2 exit latencies. */
+			memcpy(buf, &usb3_bos_descriptor,
+				USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
+		} else if (hcd->speed == HCD_USB2) {
+			memcpy(buf, &usb2_bos_descriptor,
+				USB_DT_BOS_SIZE + USB_DT_USB_EXT_CAP_SIZE);
+
+			/* Set first byte of bmAttributes in the
+			* usb2_bos_descriptor */
+			if (xhci->hw_lpm_support)
+				buf[8] |= USB_LPM_SUPPORT;
+			/* Set the BESL support bit in bmAttributes first
+			 * byte */
+			if (XHCI_BLC)
+				buf[8] |= USB_BESL_SUPPORT;
+			if (xhci->dbesl) {
+				buf[8] = USB_BESL_DEEP_VALID;
+				buf[9] = xhci->dbesl;
+			}
+			if (xhci->dbesld) {
+				buf[8] = USB_BESL_DEEP_VALID;
+				buf[9] = xhci->dbesl << 4;
+			}
+		} else
 			goto error;
 
-		/* Set the U1 and U2 exit latencies. */
-		memcpy(buf, &usb_bos_descriptor,
-				USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
 		temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
 		buf[12] = HCS_U1_LATENCY(temp);
 		put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c338741..90edeed 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1564,6 +1564,9 @@ struct xhci_hcd {
 	/* Compliance Mode Recovery Data */
 	struct timer_list	comp_mode_recovery_timer;
 	u32			port_status_u0;
+	/* LPM DBESL and BESL USB 2.0 Errata support */
+	u32			dbesl;
+	u32			dbesld;
 /* Compliance Mode Timer Triggered every 2 seconds */
 #define COMP_MODE_RCVRY_MSECS 2000
 };
-- 
1.7.9.5

--
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