All of lore.kernel.org
 help / color / mirror / Atom feed
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

  reply	other threads:[~2021-03-10  8:28 UTC|newest]

Thread overview: 15+ 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
2021-02-09  5:37 [PATCH v2 7/8] usb: xhci: Rewrite xhci_create_usb3_bos_desc() kernel test robot

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.