From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
Mathias Nyman <mathias.nyman@intel.com>
Subject: Re: [PATCH v2 7/8] usb: xhci: Rewrite xhci_create_usb3_bos_desc()
Date: Wed, 10 Mar 2021 10:28:51 +0200 [thread overview]
Message-ID: <04c53dae-69aa-b6f8-6ee8-128d3a1b47ac@linux.intel.com> (raw)
In-Reply-To: <4ccfdad5-c318-3274-74c0-871d4a6b242f@synopsys.com>
On 9.3.2021 21.32, Thinh Nguyen wrote:
> Mathias Nyman wrote:
>> On 4.2.2021 6.11, Thinh Nguyen wrote:
>>> The current xhci_create_usb3_bos_desc() uses a static bos u8 array and
>>> various magic numbers and offsets making it difficult to extend support
>>> for USB 3.2. Let's rewrite this entire function to support dual-lane in
>>> USB 3.2.
>>>
>>> The hub driver matches the port speed ID from the extended port status
>>> to the SSID of the sublink speed attributes to detect if the device
>>> supports SuperSpeed Plus. Currently we don't provide the default gen1x2
>>> and gen2x2 sublink speed capability descriptor for USB 3.2 roothub. The
>>> USB stack depends on this to detect and match the correct speed.
>>> In addition, if the xHCI host provides Protocol Speed ID (PSI)
>>> capability, then make sure to convert Protocol Speed ID Mantissa and
>>> Exponent (PSIM & PSIE) to lane speed for gen1x2 and gen2x2.
>>>
>>> Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
>>> ---
>>> Changes in v2:
>>> - Use static array for SSA per Mathias suggestion
>>> - Check bcdUSB >= 0x320 instead of bcdUSB == 0x320 per Mathias suggestion
>>> - When host uses custom PSI, SSIC is the psi_uid_count and not SSAC. I missed
>>> this when transferring the previous logic over. Previous implementation
>>> was incorrect. Let's fix it here.
>>>
>>> drivers/usb/host/xhci-hub.c | 237 +++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 235 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
>>> index 74c497fd3476..eddd139c2260 100644
>>> --- a/drivers/usb/host/xhci-hub.c
>>> +++ b/drivers/usb/host/xhci-hub.c
>>> @@ -11,6 +11,7 @@
>>>
>>> #include <linux/slab.h>
>>> #include <asm/unaligned.h>
>>> +#include <linux/bitfield.h>
>>>
>>> #include "xhci.h"
>>> #include "xhci-trace.h"
>>> @@ -52,7 +53,239 @@ static u8 usb_bos_descriptor [] = {
>>> 0xb5, 0x40, 0x0a, 0x00, /* 10Gbps, SSP, symmetric, tx, ID = 5 */
>>> };
>>>
>>> -static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
>>> +/* Default sublink speed attribute of each lane */
>>> +static u32 ssp_cap_default_ssa[] = {
>>> + 0x00050034, /* USB 3.0 SS Gen1x1 id:4 symmetric rx 5Gbps */
>>> + 0x000500b4, /* USB 3.0 SS Gen1x1 id:4 symmetric tx 5Gbps */
>>> + 0x000a4035, /* USB 3.1 SSP Gen2x1 id:5 symmetric rx 10Gbps */
>>> + 0x000a40b5, /* USB 3.1 SSP Gen2x1 id:5 symmetric tx 10Gbps */
>>> + 0x00054036, /* USB 3.2 SSP Gen1x2 id:6 symmetric rx 5Gbps */
>>> + 0x000540b6, /* USB 3.2 SSP Gen1x2 id:6 symmetric tx 5Gbps */
>>> + 0x000a4037, /* USB 3.2 SSP Gen2x2 id:7 symmetric rx 10Gbps */
>>> + 0x000a40b7, /* USB 3.2 SSP Gen2x2 id:7 symmetric tx 10Gbps */
>>> +};
>>> +
>>> +static int xhci_create_usb3x_bos_desc(struct xhci_hcd *xhci, char *buf,
>>> + u16 wLength)
>>> +{
>>> + struct usb_bos_descriptor *bos;
>>> + struct usb_ss_cap_descriptor *ss_cap;
>>> + struct usb_ssp_cap_descriptor *ssp_cap;
>>> + struct xhci_port_cap *port_cap = NULL;
>>> + u16 bcdUSB;
>>> + u32 reg;
>>> + u32 min_rate = 0;
>>> + u8 min_ssid;
>>> + u8 ssac;
>>> + u8 ssic;
>>> + int offset;
>>> + int i;
>>> +
>>> + /* BOS descriptor */
>>> + bos = (struct usb_bos_descriptor *)buf;
>>> + bos->bLength = USB_DT_BOS_SIZE;
>>> + bos->bDescriptorType = USB_DT_BOS;
>>> + bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE +
>>> + USB_DT_USB_SS_CAP_SIZE);
>>> + bos->bNumDeviceCaps = 1;
>>> +
>>> + /* Create the descriptor for port with the highest revision */
>>> + for (i = 0; i < xhci->num_port_caps; i++) {
>>> + u8 major = xhci->port_caps[i].maj_rev;
>>> + u8 minor = xhci->port_caps[i].min_rev;
>>> + u16 rev = (major << 8) | minor;
>>> +
>>> + if (i == 0 || bcdUSB < rev) {
>>> + bcdUSB = rev;
>>> + port_cap = &xhci->port_caps[i];
>>> + }
>>> + }
>>> +
>>> + if (bcdUSB >= 0x0310) {
>>> + if (port_cap->psi_count) {
>>> + u8 num_sym_ssa = 0;
>>> +
>>> + for (i = 0; i < port_cap->psi_count; i++) {
>>> + if ((port_cap->psi[i] & PLT_MASK) == PLT_SYM)
>>> + num_sym_ssa++;
>>> + }
>>> +
>>> + ssac = port_cap->psi_count + num_sym_ssa - 1;
>>> + ssic = port_cap->psi_uid_count - 1;
>>> + } else {
>>> + if (bcdUSB >= 0x0320)
>>> + ssac = 7;
>>> + else
>>> + ssac = 3;
>>> +
>>> + ssic = (ssac + 1) / 2 - 1;
>>> + }
>>> +
>>> + bos->bNumDeviceCaps++;
>>> + bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE +
>>> + USB_DT_USB_SS_CAP_SIZE +
>>> + USB_DT_USB_SSP_CAP_SIZE(ssac));
>>> + }
>>> +
>>> + if (wLength < USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE)
>>> + return wLength;
>>> +
>>> + /* SuperSpeed USB Device Capability */
>>> + ss_cap = (struct usb_ss_cap_descriptor *)&buf[USB_DT_BOS_SIZE];
>>> + ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
>>> + ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
>>> + ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
>>> + ss_cap->bmAttributes = 0; /* set later */
>>> + ss_cap->wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION);
>>> + ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
>>> + ss_cap->bU1devExitLat = 0; /* set later */
>>> + ss_cap->bU2DevExitLat = 0; /* set later */
>>> +
>>> + reg = readl(&xhci->cap_regs->hcc_params);
>>> + if (HCC_LTC(reg))
>>> + ss_cap->bmAttributes |= USB_LTM_SUPPORT;
>>> +
>>> + if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
>>> + reg = readl(&xhci->cap_regs->hcs_params3);
>>> + ss_cap->bU1devExitLat = HCS_U1_LATENCY(reg);
>>> + ss_cap->bU2DevExitLat = cpu_to_le16(HCS_U2_LATENCY(reg));
>>> + }
>>> +
>>> + if (wLength < le16_to_cpu(bos->wTotalLength))
>>> + return wLength;
>>> +
>>> + if (bcdUSB < 0x0310)
>>> + return le16_to_cpu(bos->wTotalLength);
>>> +
>>> + ssp_cap = (struct usb_ssp_cap_descriptor *)&buf[USB_DT_BOS_SIZE +
>>> + USB_DT_USB_SS_CAP_SIZE];
>>> + ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(ssac);
>>> + ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
>>> + ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE;
>>> + ssp_cap->bReserved = 0;
>>> + ssp_cap->wReserved = 0;
>>> + ssp_cap->bmAttributes =
>>> + cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_ATTRIBS, ssac) |
>>> + FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, ssic));
>>> +
>>> + if (!port_cap->psi_count) {
>>> + for (i = 0; i < ssac + 1; i++)
>>> + ssp_cap->bmSublinkSpeedAttr[i] =
>>> + cpu_to_le32(ssp_cap_default_ssa[i]);
>>> +
>>> + min_ssid = 4;
>>> + goto out;
>>> + }
>>> +
>>> + offset = 0;
>>> + for (i = 0; i < port_cap->psi_count; i++) {
>>> + u32 psi;
>>> + u32 attr;
>>> + u8 ssid;
>>> + u8 lp;
>>> + u8 lse;
>>> + u8 psie;
>>> + u16 lane_mantissa;
>>> + u16 psim;
>>> + u16 plt;
>>> +
>>> + psi = port_cap->psi[i];
>>> + ssid = XHCI_EXT_PORT_PSIV(psi);
>>> + lp = XHCI_EXT_PORT_LP(psi);
>>> + psie = XHCI_EXT_PORT_PSIE(psi);
>>> + psim = XHCI_EXT_PORT_PSIM(psi);
>>> + plt = psi & PLT_MASK;
>>> +
>>> + lse = psie;
>>> + lane_mantissa = psim;
>>> +
>>> + /* Shift to Gbps and set SSP Link Protocol if 10Gpbs */
>>> + for (; psie < USB_SSP_SUBLINK_SPEED_LSE_GBPS; psie++)
>>> + psim /= 1000;
>>> +
>>> + if (!min_rate || psim < min_rate) {
>>> + min_ssid = ssid;
>>> + min_rate = psim;
>>> + }
>>> +
>>> + /* Some host controllers don't set the link protocol for SSP */
>>> + if (psim >= 10)
>>> + lp = USB_SSP_SUBLINK_SPEED_LP_SSP;
>> Maybe we should limit the above fix to older than USB 3.2 hosts.
>> xHCI supporting Gen 1x2 can in theory have psim==10 even if it only supports
>> SS link protocol, not SSP.
>
> Gen 1x2 uses SuperSpeed Plus link protocol. See USB 3.2 spec section 3.2
>
Yes, you're right. I got so used to Gen 1 always being SS, and Gen 2 SSP in USB 3.1.
Then those specific workarounds you made also makes sense.
From xhci POV this looks good.
Thanks
-Mathias
next prev parent reply other threads:[~2021-03-10 8:28 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-04 4:10 [PATCH v2 0/8] usb: Check for genXxY on host Thinh Nguyen
2021-02-04 4:10 ` [PATCH v2 1/8] usb: core: Track SuperSpeed Plus GenXxY Thinh Nguyen
2021-02-04 4:10 ` [PATCH v2 2/8] usb: core: hub: Remove port_speed_is_ssp() Thinh Nguyen
2021-02-04 4:10 ` [PATCH v2 3/8] usb: core: hub: Print speed name based on ssp rate Thinh Nguyen
2021-03-10 8:37 ` Mathias Nyman
2021-03-11 3:46 ` Thinh Nguyen
2021-02-04 4:10 ` [PATCH v2 4/8] usb: core: sysfs: Check for SSP rate in speed attr Thinh Nguyen
2021-02-04 4:11 ` [PATCH v2 5/8] usb: xhci: Init root hub SSP rate Thinh Nguyen
2021-02-04 4:11 ` [PATCH v2 6/8] usb: xhci: Fix port minor revision Thinh Nguyen
2021-02-04 4:11 ` [PATCH v2 7/8] usb: xhci: Rewrite xhci_create_usb3_bos_desc() Thinh Nguyen
2021-03-09 11:47 ` Mathias Nyman
2021-03-09 19:32 ` Thinh Nguyen
2021-03-10 8:28 ` Mathias Nyman [this message]
2021-02-04 4:11 ` [PATCH v2 8/8] usb: xhci: Remove unused function Thinh Nguyen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=04c53dae-69aa-b6f8-6ee8-128d3a1b47ac@linux.intel.com \
--to=mathias.nyman@linux.intel.com \
--cc=Thinh.Nguyen@synopsys.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).