Modified xHCI roothub descriptor to return USB2.0 extension descriptor
with BESL and DBESL values set when these values are set on the xHCI
host.

Curretnly the root hub device descriptor values are 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 set the bcdUSB
bit to 0x01.

Here is the test output.
$ 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.ya...@intel.com>
---
 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..60601df 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 3.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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to