Re: [RFC v3] xhci-hub: Roothub USB2.0 descriptor for BESL DBESL

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

 



Paul,
Thank you for catching the bug.

Sarah,
Thank you for the detailed description and explanation on the changes.  I
will send the patch shortly with the updated changes and test.

Alexandra.

> On Sat, Aug 10, 2013 at 04:04:02AM +0000, Paul Zimmerman wrote:
>> > From: linux-usb-owner@xxxxxxxxxxxxxxx
>> [mailto:linux-usb-owner@xxxxxxxxxxxxxxx] On Behalf Of Alexandra Yates
>> > Sent: Friday, August 09, 2013 12:21 PM
>>
>> Hi Alexandra,
>>
>> <snip>
>>
>> >
>> > +/* 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 */
>>
>> Here you hard-code the first byte of bmAttributes, so LPM Supported,
>> BESL
>> Supported etc. are already set...
>
> Yes, Paul is right, you need to set this value to 0x00 in the initial
> structure.
>
>> > +	0xff,                           /* bmAttributes - second byte:
>> > +					   8-11bit:BESL and 12-16bit:DBESL*/
>
> You also need to set this to 0x00.
>
>> > +	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;
>>
>> ...so these two lines have no effect, the bit is already set.
>
> Then OR'ing in the USB_LPM_SUPPORT bit will work here.
>
> Further, we want to tell lsusb that the USB 2.0 roothub has Link PM
> support if the host controller supports either software-controlled Link
> PM, or hardware-controlled link PM.  The USB core only works with
> hardware-controlled Link PM, but we could add software controlled link
> PM in the future.
>
> In xhci-mem.c:xhci_add_in_port(), xhci->sw_lpm_support is set if the
> host supports USB 2.0 link PM.  If the host supports hardware-controlled
> Link PM, xhci->hw_lpm_support is additionally set.
>
> Your code currently only works for hosts that support
> hardware-controlled Link PM.  You should change this line:
>
> +			if (xhci->hw_lpm_support)
> +				buf[8] |= USB_LPM_SUPPORT;
>
> To
>
> +			if (xhci->sw_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;
>> > +                       }
>
> The math here is off, and your initialization of the structure hid those
> issues.  You should have used USB_BESL_BASELINE_VALID in the second if
> block instead of using USB_BESL_DEEP_VALID twice.  In the third if
> statement block, I think you meant to use xhci->dbesld not xhci->dbesl.
>
> Finally, you overwrote the contents of buf[8] and buf[9] in the two if
> statements, which means USB_LPM_SUPPORT and USB_BESL_SUPPORT would never
> be set in buf[8], and if xhci->dbesl and xhci->dbesld were both set,
> buf[9] would only contain the deep BESL value.  You probably meant to
> use |= instead of = for all the assignments in those last two if
> blocks.
>
>> > 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
>> > };
>
> You defined these new values, but you don't set them any where in the
> code.  I think this was one of the areas where you were stuck, when we
> discussed this last.  Sorry for not getting back to you on this sooner.
> Here's what I would like you to do.
>
> First, the xHCI driver ignores any BESL deep values from the device, and
> only uses the BESL values.  Therefore, we shouldn't report the deep BESL
> value in the USB 2.0 BOS descriptor, and we shouldn't set
> USB_BESL_DEEP_VALID.  We should only report the BESL value if the host
> supports BESL for any of the roothub ports.
>
> So, how do we know if the host supports the BESL encoding for the
> roothub ports?  To do that, we need to look at the port's extended
> capabilities register.  The code in xhci_add_in_port() caches those
> capabilities in xhci->ext_caps:
>
>         /* cache usb2 port capabilities */
>         if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
>                 xhci->ext_caps[xhci->num_ext_caps++] = temp;
>
> Code in xhci_update_device() later checks the extended capabilities for
> the port to see if it supports the BESL encoding:
>
>                         if (xhci_check_usb2_port_capability(xhci, portnum,
>                                                             XHCI_BLC))
>
> That function checks the xhci->ext_caps for that port to see if the bit
> (XHCI_BLC) is set:
>
> /* check if a usb2 port supports a given extened capability protocol
>  * only USB2 ports extended protocol capability values are cached.
>  * Return 1 if capability is supported
>  */
> static int xhci_check_usb2_port_capability(struct xhci_hcd *xhci, int
> port,
>                                            unsigned capability)
> {
>         u32 port_offset, port_count;
>         int i;
>
>         for (i = 0; i < xhci->num_ext_caps; i++) {
>                 if (xhci->ext_caps[i] & capability) {
>                         /* port offsets starts at 1 */
>                         port_offset = XHCI_EXT_PORT_OFF(xhci->ext_caps[i])
> - 1;
>                         port_count =
> XHCI_EXT_PORT_COUNT(xhci->ext_caps[i]);
>                         if (port >= port_offset &&
>                             port < port_offset + port_count)
>                                 return 1;
>                 }
>         }
>         return 0;
> }
>
> Basically, if any of the USB 2.0 ports support the BESL encoding, some
> array entry in xhci->ext_caps will have XHCI_BLC set.  If that bit is
> set for any of the USB 2.0 registers, the roothub descriptor should have
> USB_BESL_BASELINE_VALID set.
>
> Now, what do we set the value of the baseline BESL to be in the hub
> descriptor?
>
> The xHCI BESL and DSBESL values are actually in the PCI configuration
> registers.  However, the xHCI driver doesn't actually use those values
> from the PCI registers.  Instead, it ignores the deep BESL values, and
> uses a default BESL value of XHCI_DEFAULT_BESL.  XHCI_DEFAULT_BESL is
> defined as 4, which means a BESL value of 400 microseconds (see the
> Table X-X1. BESL & HIRD Encodings).
>
> We only use the XHCI_DEFAULT_BESL if the USB 2.0 port register in the
> extended capabilities section has BLC set.
>
> So here's what you should do:
>
> 1. Delete xhci->dbesld from your patch.
>
> 2. Change the name from xhci->dbesl to just xhci->besl.  The USB spec
> refers to it as baseline BESL, even though the PCI spec refers to it as
> default BESL.  It's confusing, so let's stick with the USB version,
> since this is a USB driver.
>
> 2. In xhci_add_in_port(), if any port capability has the XHCI_BLC set,
> set xhci->besl to XHCI_DEFAULT_BESL, i.e.:
>
>                 if (xhci->ext_caps[i] & XHCI_BLC)
> 			xhci->besl = XHCI_DEFAULT_BESL;
>
> 3. Where XHCI_DEFAULT_BESL is used in xhci_update_device() in xhci.c,
> change it to use xhci->besl instead.
>
> 4. Zero the USB 2.0 BOS descriptors as I mentioned above.
>
> 5. Change your math in the BOS descriptor to be:
>
> +                       /* Set the BESL support bit in bmAttributes */
> +                       if (xhci->besl) {
> +                               buf[8] |= USB_BESL_SUPPORT;
> +                               buf[8] |= USB_BESL_BASELINE_VALID;
> +                               buf[9] = xhci->besl;
> +                       }
>
> Does that make sense?  If you have any questions, you can get me on IRC.
> I may not be in the office tomorrow, but I will definitely be in the
> office on Thursday.
>
> Sarah Sharp
>


Thank you,
Alexandra.
--
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