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

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

 



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.yates@xxxxxxxxx>
---
 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 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