On Wed, 5 Oct 2011, Sarah Sharp wrote: > To add USB 3.0 link power management (LPM), we need to know what the U1 > and U2 exit latencies are for the xHCI host controller. External USB 3.0 > hubs report these values through the SuperSpeed Capabilities descriptor in > the BOS descriptor. Make the USB 3.0 roothub for the xHCI host behave > like an external hub and return the BOS descriptors. > > The U1 and U2 exit latencies will vary across each host controller, so we > need to dynamically fill those values in by reading the exit latencies out > of the xHC registers. Make the roothub code in the USB core handle > hub_control() returning the length of the data copied. > > Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> > --- > > Like so? Yes, with just a few alterations... > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > index 73cbbd8..8b66a4f 100644 > --- a/drivers/usb/core/hcd.c > +++ b/drivers/usb/core/hcd.c > @@ -442,7 +442,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) > struct usb_ctrlrequest *cmd; > u16 typeReq, wValue, wIndex, wLength; > u8 *ubuf = urb->transfer_buffer; > - u8 tbuf [sizeof (struct usb_hub_descriptor)] > + u8 tbuf [USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE] Get rid of the space before the '['. Dave Brownell used to like having a space before his opening brackets and parens, but it's not the standard kernel style. Also, it would be a good idea to add a comment about the array size. The array needs to be big enough to hold the BOS descriptor + the SS Device Capability descriptor, as well as big enough to hold a usb_hub_descriptor. As it happens, both come out to 15 bytes. But if things change in the future, people will need to know what's going on. > --- a/drivers/usb/host/xhci-hub.c > +++ b/drivers/usb/host/xhci-hub.c > @@ -28,6 +28,25 @@ > #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ > PORT_RC | PORT_PLC | PORT_PE) > > +/* usb 1.1 root hub device descriptor */ > +static u8 usb_bos_descriptor [] = { > + USB_DT_BOS_SIZE, /* __u8 bLength */ > + USB_DT_BOS, /* __u8 bDescriptorType */ > + 0x0F, 0x00, /* __le16 wTotalLength, 15 bytes */ > + 0x1, /* __u8 bNumDeviceCaps */ > + /* First device capability */ > + USB_DT_USB_SS_CAP_SIZE, /* __u8 bLength, 10 bytes */ > + 0x10, /* Device Capability; value = 16 */ This should be USB_DT_DEVICE_CAPABILITY. > + USB_SS_CAP_TYPE, /* bDevCapabilityType, SUPERSPEED_USB */ > + 0x00, /* bmAttributes, LTM off by default */ > + USB_5GBPS_OPERATION, 0x00, /* wSpeedsSupported, 5Gbps only */ > + 0x03, /* bFunctionalitySupport, > + USB 3.0 speed only */ > + 0x00, /* bU1DevExitLat, set later. */ > + 0x00, 0x00 /* __le16 bU2DevExitLat, set later. */ > +}; > + > + > static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, > struct usb_hub_descriptor *desc, int ports) > { > @@ -455,6 +474,20 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, > xhci_hub_descriptor(hcd, xhci, > (struct usb_hub_descriptor *) buf); > break; > + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: > + if ((wValue & 0xff00) != (USB_DT_BOS << 8)) > + goto error; > + > + if (hcd->speed != HCD_USB3) > + goto error; > + > + memcpy(buf, &usb_bos_descriptor, sizeof(usb_bos_descriptor)); > + temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); > + buf[12] = HCS_U1_LATENCY(temp); > + put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); > + > + spin_unlock_irqrestore(&xhci->lock, flags); > + return sizeof(usb_bos_descriptor); This should return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE. Alan Stern -- 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