usb: core: Track SuperSpeed Plus GenXxY
[ Upstream commit 0299809be415567366b66f248eed93848b8dc9f3 ] Introduce ssp_rate field to usb_device structure to capture the connected SuperSpeed Plus signaling rate generation and lane count with the corresponding usb_ssp_rate enum. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/b7805d121e5ae4ad5ae144bd860b6ac04ee47436.1615432770.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Stable-dep-of: f74a7afc224a ("usb: hub: Guard against accesses to uninitialized BOS descriptors") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
d6316f5929
commit
95b9f1e392
@@ -2745,6 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||||||
|
|
||||||
rhdev->rx_lanes = 1;
|
rhdev->rx_lanes = 1;
|
||||||
rhdev->tx_lanes = 1;
|
rhdev->tx_lanes = 1;
|
||||||
|
rhdev->ssp_rate = USB_SSP_GEN_UNKNOWN;
|
||||||
|
|
||||||
switch (hcd->speed) {
|
switch (hcd->speed) {
|
||||||
case HCD_USB11:
|
case HCD_USB11:
|
||||||
@@ -2762,8 +2763,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||||||
case HCD_USB32:
|
case HCD_USB32:
|
||||||
rhdev->rx_lanes = 2;
|
rhdev->rx_lanes = 2;
|
||||||
rhdev->tx_lanes = 2;
|
rhdev->tx_lanes = 2;
|
||||||
fallthrough;
|
rhdev->ssp_rate = USB_SSP_GEN_2x2;
|
||||||
|
rhdev->speed = USB_SPEED_SUPER_PLUS;
|
||||||
|
break;
|
||||||
case HCD_USB31:
|
case HCD_USB31:
|
||||||
|
rhdev->ssp_rate = USB_SSP_GEN_2x1;
|
||||||
rhdev->speed = USB_SPEED_SUPER_PLUS;
|
rhdev->speed = USB_SPEED_SUPER_PLUS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include <linux/pm_qos.h>
|
#include <linux/pm_qos.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
@@ -2691,6 +2692,81 @@ out_authorized:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_port_ssp_rate - Match the extended port status to SSP rate
|
||||||
|
* @hdev: The hub device
|
||||||
|
* @ext_portstatus: extended port status
|
||||||
|
*
|
||||||
|
* Match the extended port status speed id to the SuperSpeed Plus sublink speed
|
||||||
|
* capability attributes. Base on the number of connected lanes and speed,
|
||||||
|
* return the corresponding enum usb_ssp_rate.
|
||||||
|
*/
|
||||||
|
static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev,
|
||||||
|
u32 ext_portstatus)
|
||||||
|
{
|
||||||
|
struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap;
|
||||||
|
u32 attr;
|
||||||
|
u8 speed_id;
|
||||||
|
u8 ssac;
|
||||||
|
u8 lanes;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ssp_cap)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
speed_id = ext_portstatus & USB_EXT_PORT_STAT_RX_SPEED_ID;
|
||||||
|
lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1;
|
||||||
|
|
||||||
|
ssac = le32_to_cpu(ssp_cap->bmAttributes) &
|
||||||
|
USB_SSP_SUBLINK_SPEED_ATTRIBS;
|
||||||
|
|
||||||
|
for (i = 0; i <= ssac; i++) {
|
||||||
|
u8 ssid;
|
||||||
|
|
||||||
|
attr = le32_to_cpu(ssp_cap->bmSublinkSpeedAttr[i]);
|
||||||
|
ssid = FIELD_GET(USB_SSP_SUBLINK_SPEED_SSID, attr);
|
||||||
|
if (speed_id == ssid) {
|
||||||
|
u16 mantissa;
|
||||||
|
u8 lse;
|
||||||
|
u8 type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: currently asymmetric lane types are only
|
||||||
|
* applicable for SSIC operate in SuperSpeed protocol
|
||||||
|
*/
|
||||||
|
type = FIELD_GET(USB_SSP_SUBLINK_SPEED_ST, attr);
|
||||||
|
if (type == USB_SSP_SUBLINK_SPEED_ST_ASYM_RX ||
|
||||||
|
type == USB_SSP_SUBLINK_SPEED_ST_ASYM_TX)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (FIELD_GET(USB_SSP_SUBLINK_SPEED_LP, attr) !=
|
||||||
|
USB_SSP_SUBLINK_SPEED_LP_SSP)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
lse = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSE, attr);
|
||||||
|
mantissa = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSM, attr);
|
||||||
|
|
||||||
|
/* Convert to Gbps */
|
||||||
|
for (; lse < USB_SSP_SUBLINK_SPEED_LSE_GBPS; lse++)
|
||||||
|
mantissa /= 1000;
|
||||||
|
|
||||||
|
if (mantissa >= 10 && lanes == 1)
|
||||||
|
return USB_SSP_GEN_2x1;
|
||||||
|
|
||||||
|
if (mantissa >= 10 && lanes == 2)
|
||||||
|
return USB_SSP_GEN_2x2;
|
||||||
|
|
||||||
|
if (mantissa >= 5 && lanes == 2)
|
||||||
|
return USB_SSP_GEN_1x2;
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return USB_SSP_GEN_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return 1 if port speed is SuperSpeedPlus, 0 otherwise or if the
|
* Return 1 if port speed is SuperSpeedPlus, 0 otherwise or if the
|
||||||
* capability couldn't be checked.
|
* capability couldn't be checked.
|
||||||
@@ -2878,9 +2954,11 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
|||||||
/* extended portstatus Rx and Tx lane count are zero based */
|
/* extended portstatus Rx and Tx lane count are zero based */
|
||||||
udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1;
|
udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1;
|
||||||
udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1;
|
udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1;
|
||||||
|
udev->ssp_rate = get_port_ssp_rate(hub->hdev, ext_portstatus);
|
||||||
} else {
|
} else {
|
||||||
udev->rx_lanes = 1;
|
udev->rx_lanes = 1;
|
||||||
udev->tx_lanes = 1;
|
udev->tx_lanes = 1;
|
||||||
|
udev->ssp_rate = USB_SSP_GEN_UNKNOWN;
|
||||||
}
|
}
|
||||||
if (hub_is_wusb(hub))
|
if (hub_is_wusb(hub))
|
||||||
udev->speed = USB_SPEED_WIRELESS;
|
udev->speed = USB_SPEED_WIRELESS;
|
||||||
|
@@ -565,6 +565,7 @@ struct usb3_lpm_parameters {
|
|||||||
* @speed: device speed: high/full/low (or error)
|
* @speed: device speed: high/full/low (or error)
|
||||||
* @rx_lanes: number of rx lanes in use, USB 3.2 adds dual-lane support
|
* @rx_lanes: number of rx lanes in use, USB 3.2 adds dual-lane support
|
||||||
* @tx_lanes: number of tx lanes in use, USB 3.2 adds dual-lane support
|
* @tx_lanes: number of tx lanes in use, USB 3.2 adds dual-lane support
|
||||||
|
* @ssp_rate: SuperSpeed Plus phy signaling rate and lane count
|
||||||
* @tt: Transaction Translator info; used with low/full speed dev, highspeed hub
|
* @tt: Transaction Translator info; used with low/full speed dev, highspeed hub
|
||||||
* @ttport: device port on that tt hub
|
* @ttport: device port on that tt hub
|
||||||
* @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
|
* @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
|
||||||
@@ -642,6 +643,7 @@ struct usb_device {
|
|||||||
enum usb_device_speed speed;
|
enum usb_device_speed speed;
|
||||||
unsigned int rx_lanes;
|
unsigned int rx_lanes;
|
||||||
unsigned int tx_lanes;
|
unsigned int tx_lanes;
|
||||||
|
enum usb_ssp_rate ssp_rate;
|
||||||
|
|
||||||
struct usb_tt *tt;
|
struct usb_tt *tt;
|
||||||
int ttport;
|
int ttport;
|
||||||
|
Reference in New Issue
Block a user