[PATCH v5] 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 result of 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   0x0000040e
      BESL Link Power Management (LPM) Supported
    BESL value     1024 us
Device Status:     0x0001
  Self Powered

Signed-off-by: Alexandra Yates <alexandra.yates@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-hub.c |   44 ++++++++++++++++++++++++++++++++++++++-----
 drivers/usb/host/xhci-mem.c |    5 ++++-
 drivers/usb/host/xhci.h     |    1 +
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1d35459..431af44 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 */
+	0x00,                           /* bmAttributes first byte: bit1:LPM
+					   Supported, bit2: BESL supported,
+					   bit3:valid  baseline BESL, bit4:
+					   valid Deep BESL, bits5-7 */
+	0x00,                           /* 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,24 @@ 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 the BESL support bit in bmAttributes first
+			 * byte */
+			if (xhci->besl) {
+				buf[8] |= USB_BESL_SUPPORT;
+				buf[8] |= USB_BESL_BASELINE_VALID;
+				buf[9] = xhci->besl;
+			}
+		} 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-mem.c b/drivers/usb/host/xhci-mem.c
index df6978a..a31933f 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2070,7 +2070,10 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 
 	/* cache usb2 port capabilities */
 	if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
-		xhci->ext_caps[xhci->num_ext_caps++] = temp;
+		xhci->ext_caps[xhci->num_ext_caps] = temp;
+
+	if (xhci->ext_caps[xhci->num_ext_caps++] & XHCI_BLC)
+		xhci->besl = XHCI_DEFAULT_BESL;
 
 	/* Check the host's USB2 LPM capability */
 	if ((xhci->hci_version == 0x96) && (major_revision != 0x03) &&
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c338741..8591a05 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1564,6 +1564,7 @@ struct xhci_hcd {
 	/* Compliance Mode Recovery Data */
 	struct timer_list	comp_mode_recovery_timer;
 	u32			port_status_u0;
+	u8			besl;
 /* 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