forked from Minki/linux
usb: gadget: composite: Report various SSP sublink speeds
If a gadget supports SuperSpeed Plus, then it may operate in different sublink speeds. For example, if the gadget supports SuperSpeed Plus gen2x2, then it can support 2 sublink speeds gen1 and gen2. Inform the host of these speeds in the BOS descriptor. Use 1 SSID if the gadget supports up to gen2x1, or not specified: - SSID 0 for symmetric RX/TX sublink speed of 10 Gbps. Use 1 SSID if the gadget supports up to gen1x2: - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps. Use 2 SSIDs if the gadget supports up to gen2x2: - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps. - SSID 1 for symmetric RX/TX sublink speed of 10 Gbps. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/eb0386fdd5d87a858281e8006a72723d3732240f.1610592135.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ead4c12485
commit
7bf0fc5a6b
@ -735,49 +735,77 @@ static int bos_desc(struct usb_composite_dev *cdev)
|
||||
/* The SuperSpeedPlus USB Device Capability descriptor */
|
||||
if (gadget_is_superspeed_plus(cdev->gadget)) {
|
||||
struct usb_ssp_cap_descriptor *ssp_cap;
|
||||
u8 ssac = 1;
|
||||
u8 ssic;
|
||||
int i;
|
||||
|
||||
if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x2)
|
||||
ssac = 3;
|
||||
|
||||
/*
|
||||
* Paired RX and TX sublink speed attributes share
|
||||
* the same SSID.
|
||||
*/
|
||||
ssic = (ssac + 1) / 2 - 1;
|
||||
|
||||
ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
|
||||
bos->bNumDeviceCaps++;
|
||||
|
||||
/*
|
||||
* Report typical values.
|
||||
*/
|
||||
|
||||
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(1));
|
||||
ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1);
|
||||
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(ssac));
|
||||
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, 1) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, 0));
|
||||
cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_ATTRIBS, ssac) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, ssic));
|
||||
|
||||
ssp_cap->wFunctionalitySupport =
|
||||
cpu_to_le16(FIELD_PREP(USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, 0) |
|
||||
FIELD_PREP(USB_SSP_MIN_RX_LANE_COUNT, 1) |
|
||||
FIELD_PREP(USB_SSP_MIN_TX_LANE_COUNT, 1));
|
||||
|
||||
ssp_cap->bmSublinkSpeedAttr[0] =
|
||||
cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, 0) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE,
|
||||
USB_SSP_SUBLINK_SPEED_LSE_GBPS) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
|
||||
USB_SSP_SUBLINK_SPEED_ST_SYM_RX) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP,
|
||||
USB_SSP_SUBLINK_SPEED_LP_SSP) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, 10));
|
||||
/*
|
||||
* Use 1 SSID if the gadget supports up to gen2x1 or not
|
||||
* specified:
|
||||
* - SSID 0 for symmetric RX/TX sublink speed of 10 Gbps.
|
||||
*
|
||||
* Use 1 SSID if the gadget supports up to gen1x2:
|
||||
* - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps.
|
||||
*
|
||||
* Use 2 SSIDs if the gadget supports up to gen2x2:
|
||||
* - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps.
|
||||
* - SSID 1 for symmetric RX/TX sublink speed of 10 Gbps.
|
||||
*/
|
||||
for (i = 0; i < ssac + 1; i++) {
|
||||
u8 ssid;
|
||||
u8 mantissa;
|
||||
u8 type;
|
||||
|
||||
ssp_cap->bmSublinkSpeedAttr[1] =
|
||||
cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, 0) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE,
|
||||
USB_SSP_SUBLINK_SPEED_LSE_GBPS) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
|
||||
USB_SSP_SUBLINK_SPEED_ST_SYM_TX) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP,
|
||||
USB_SSP_SUBLINK_SPEED_LP_SSP) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, 10));
|
||||
ssid = i >> 1;
|
||||
|
||||
if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x1 ||
|
||||
cdev->gadget->max_ssp_rate == USB_SSP_GEN_UNKNOWN)
|
||||
mantissa = 10;
|
||||
else
|
||||
mantissa = 5 << ssid;
|
||||
|
||||
if (i % 2)
|
||||
type = USB_SSP_SUBLINK_SPEED_ST_SYM_TX;
|
||||
else
|
||||
type = USB_SSP_SUBLINK_SPEED_ST_SYM_RX;
|
||||
|
||||
ssp_cap->bmSublinkSpeedAttr[i] =
|
||||
cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, ssid) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE,
|
||||
USB_SSP_SUBLINK_SPEED_LSE_GBPS) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST, type) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP,
|
||||
USB_SSP_SUBLINK_SPEED_LP_SSP) |
|
||||
FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, mantissa));
|
||||
}
|
||||
}
|
||||
|
||||
return le16_to_cpu(bos->wTotalLength);
|
||||
|
Loading…
Reference in New Issue
Block a user