git: 85c3bd4595ba - main - usb: support SSP/SSPx2 devices in all-speed consumers

From: ShengYi Hung <aokblast_at_FreeBSD.org>
Date: Mon, 02 Nov 2026 03:02:46 UTC
The branch main has been updated by aokblast:

URL: https://cgit.FreeBSD.org/src/commit/?id=85c3bd4595ba3d213ef570a51b517d82cd481d0a

commit 85c3bd4595ba3d213ef570a51b517d82cd481d0a
Author:     ShengYi Hung <aokblast@FreeBSD.org>
AuthorDate: 2026-05-22 15:48:49 +0000
Commit:     ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2026-11-02 03:02:11 +0000

    usb: support SSP/SSPx2 devices in all-speed consumers
    
    Handle the new speeds wherever USB_SPEED_SUPER was checked.  Most
    consumers treat them as SS.
    
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D57198
---
 sys/dev/rtwn/rtl8812a/usb/r12au_attach.c |  2 +-
 sys/dev/usb/controller/usb_controller.c  | 12 ++++++++++++
 sys/dev/usb/controller/xhci.c            |  4 ++--
 sys/dev/usb/net/if_muge.c                |  6 ++++++
 sys/dev/usb/net/if_ure.c                 |  9 ++++++---
 sys/dev/usb/storage/umass.c              |  8 ++++++++
 sys/dev/usb/template/usb_template.c      |  9 +++++++++
 sys/dev/usb/usb_device.c                 |  2 +-
 sys/dev/usb/usb_request.c                |  5 ++---
 sys/dev/usb/usb_transfer.c               | 18 ++++++++++++++++++
 10 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
index 069fb28d5be7..57e4d8b0091c 100644
--- a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
+++ b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
@@ -78,7 +78,7 @@ r12au_postattach(struct rtwn_softc *sc)
 	struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
 	struct r12a_softc *rs = sc->sc_priv;
 
-	if (usbd_get_speed(uc->uc_udev) == USB_SPEED_SUPER) {
+	if (usbd_get_speed(uc->uc_udev) >= USB_SPEED_SUPER) {
 		rs->ac_usb_dma_size = 0x07;
 		rs->ac_usb_dma_time = 0x1a;
 	} else {
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 3eb632124b4c..46377551d51d 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -737,6 +737,18 @@ usb_bus_attach(struct usb_proc_msg *pm)
 		device_printf(bus->bdev, "5.0Gbps Super Speed USB v3.0\n");
 		break;
 
+	case USB_REV_3_1:
+		speed = USB_SPEED_SUPER_PLUS;
+		device_printf(bus->bdev,
+		    "10Gbps Super Speed Plus USB v3.1\n");
+		break;
+
+	case USB_REV_3_2:
+		speed = USB_SPEED_SUPER_PLUS_GEN2_X2;
+		device_printf(bus->bdev,
+		    "20Gbps Super Speed Plus USB v3.2\n");
+		break;
+
 	default:
 		device_printf(bus->bdev, "Unsupported USB revision\n");
 #if USB_HAVE_ROOT_MOUNT_HOLD
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 72a0b704b9b6..acc6eee525b0 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -4537,9 +4537,9 @@ xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
 	case USB_EP_MODE_DEFAULT:
 		return (0);
 	case USB_EP_MODE_STREAMS:
-		if (xhcistreams == 0 || 
+		if (xhcistreams == 0 ||
 		    (ep->edesc->bmAttributes & UE_XFERTYPE) != UE_BULK ||
-		    udev->speed != USB_SPEED_SUPER)
+		    udev->speed < USB_SPEED_SUPER)
 			return (USB_ERR_INVAL);
 		return (0);
 	default:
diff --git a/sys/dev/usb/net/if_muge.c b/sys/dev/usb/net/if_muge.c
index a39343b2e3c9..56ffa0c67d9a 100644
--- a/sys/dev/usb/net/if_muge.c
+++ b/sys/dev/usb/net/if_muge.c
@@ -817,6 +817,9 @@ lan78xx_miibus_statchg(device_t dev)
 	/* XXX Flow control settings obtained from Microchip's driver. */
 	switch(usbd_get_speed(sc->sc_ue.ue_udev)) {
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_X2:
+	case USB_SPEED_SUPER_PLUS_GEN2_X2:
 		fct_flow = 0x817;
 		break;
 	case USB_SPEED_HIGH:
@@ -1023,6 +1026,9 @@ lan78xx_chip_init(struct muge_softc *sc)
 	/* Configuring the burst cap. */
 	switch (usbd_get_speed(sc->sc_ue.ue_udev)) {
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_X2:
+	case USB_SPEED_SUPER_PLUS_GEN2_X2:
 		burst_cap = MUGE_DEFAULT_BURST_CAP_SIZE/MUGE_SS_USB_PKT_SIZE;
 		break;
 	case USB_SPEED_HIGH:
diff --git a/sys/dev/usb/net/if_ure.c b/sys/dev/usb/net/if_ure.c
index 81e1232a0e64..a3468d7869f4 100644
--- a/sys/dev/usb/net/if_ure.c
+++ b/sys/dev/usb/net/if_ure.c
@@ -1151,6 +1151,9 @@ ure_init(struct usb_ether *ue)
 	/* Set RX EARLY timeout and size */
 	if (sc->sc_flags & URE_FLAG_8153) {
 		switch (usbd_get_speed(sc->sc_ue.ue_udev)) {
+		case USB_SPEED_SUPER_PLUS_GEN2_X2:
+		case USB_SPEED_SUPER_PLUS_X2:
+		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:
 			reg = URE_COALESCE_SUPER / 8;
 			break;
@@ -1701,7 +1704,7 @@ ure_rtl8153_init(struct ure_softc *sc)
 	URE_CLRBIT_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, URE_LED_MODE_MASK);
 
 	if ((sc->sc_chip & URE_CHIP_VER_5C10) &&
-	    usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_SUPER)
+	    usbd_get_speed(sc->sc_ue.ue_udev) < USB_SPEED_SUPER)
 		val = URE_LPM_TIMER_500MS;
 	else
 		val = URE_LPM_TIMER_500US;
@@ -1883,7 +1886,7 @@ ure_rtl8153b_init(struct ure_softc *sc)
 	ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
 
 	/* Enable U1U2 */
-	if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_SUPER)
+	if (usbd_get_speed(sc->sc_ue.ue_udev) >= USB_SPEED_SUPER)
 		URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, URE_LPM_U1U2_EN);
 
 	if (sc->sc_flags & URE_FLAG_8156B) {
@@ -2050,7 +2053,7 @@ ure_rtl8153b_nic_reset(struct ure_softc *sc)
 	}
 
 	/* Enable U1U2 */
-	if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_SUPER)
+	if (usbd_get_speed(sc->sc_ue.ue_udev) >= USB_SPEED_SUPER)
 		URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, URE_LPM_U1U2_EN);
 }
 
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 0ee6ea992fa7..adab90d30690 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -222,6 +222,7 @@ SYSCTL_INT(_hw_usb_umass, OID_AUTO, throttle, CTLFLAG_RWTUN,
 #define	UMASS_FULL_TRANSFER_SPEED	1000
 #define	UMASS_HIGH_TRANSFER_SPEED	40000
 #define	UMASS_SUPER_TRANSFER_SPEED	400000
+#define	UMASS_SUPER_PLUS_TRANSFER_SPEED	1000000
 #define	UMASS_FLOPPY_TRANSFER_SPEED	20
 
 #define	UMASS_TIMEOUT			5000	/* ms */
@@ -2409,6 +2410,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
 					    UMASS_FLOPPY_TRANSFER_SPEED;
 				} else {
 					switch (usbd_get_speed(sc->sc_udev)) {
+					case USB_SPEED_SUPER_PLUS_GEN2_X2:
+					case USB_SPEED_SUPER_PLUS_X2:
+					case USB_SPEED_SUPER_PLUS:
+						cpi->base_transfer_speed =
+						    UMASS_SUPER_PLUS_TRANSFER_SPEED;
+						cpi->maxio = maxphys;
+						break;
 					case USB_SPEED_SUPER:
 						cpi->base_transfer_speed =
 						    UMASS_SUPER_TRANSFER_SPEED;
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index 6e9de2a6dcce..a26c643a860d 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -593,6 +593,15 @@ usb_make_device_desc(struct usb_temp_setup *temp,
 			USETW(utd->udd.bcdUSB, 0x0300);
 			utd->udd.bMaxPacketSize = 9;	/* 2**9 = 512 bytes */
 			break;
+		case USB_SPEED_SUPER_PLUS:
+			USETW(utd->udd.bcdUSB, 0x0310);
+			utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */
+			break;
+		case USB_SPEED_SUPER_PLUS_X2:
+		case USB_SPEED_SUPER_PLUS_GEN2_X2:
+			USETW(utd->udd.bcdUSB, 0x0320);
+			utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */
+			break;
 		default:
 			temp->err = USB_ERR_INVAL;
 			break;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 4e0268110787..24cce9a47f50 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -524,7 +524,7 @@ usb_init_endpoint(struct usb_device *udev, uint8_t iface_index,
 		return;
 
 	/* check for SUPER-speed streams mode endpoint */
-	if (udev->speed == USB_SPEED_SUPER && ecomp != NULL &&
+	if (udev->speed >= USB_SPEED_SUPER && ecomp != NULL &&
 	    (edesc->bmAttributes & UE_XFERTYPE) == UE_BULK &&
 	    (UE_GET_BULK_STREAMS(ecomp->bmAttributes) != 0)) {
 		usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_STREAMS);
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index 55e5f04194d9..879d57f00eec 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -2081,8 +2081,7 @@ retry:
 	 * Try to reset the High Speed parent HUB of a LOW- or FULL-
 	 * speed device, if any.
 	 */
-	if (udev->parent_hs_hub != NULL &&
-	    udev->speed != USB_SPEED_HIGH) {
+	if (udev->parent_hs_hub != NULL && udev->speed < USB_SPEED_HIGH) {
 		DPRINTF("Trying to reset parent High Speed TT.\n");
 		if (udev->parent_hs_hub == parent_hub &&
 		    (uhub_count_active_host_ports(parent_hub, USB_SPEED_LOW) +
@@ -2103,7 +2102,7 @@ retry:
 	}
 #endif
 	/* Try to warm reset first */
-	if (parent_hub->speed == USB_SPEED_SUPER)
+	if (parent_hub->speed >= USB_SPEED_SUPER)
 		usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);
 
 	/* Try to reset the parent HUB port. */
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index d41121ed3a06..751014699a44 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -407,6 +407,9 @@ usbd_get_max_frame_length(const struct usb_endpoint_descriptor *edesc,
 		max_packet_size &= 0x7FF;
 		break;
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_X2:
+	case USB_SPEED_SUPER_PLUS_GEN2_X2:
 		max_packet_count += (max_packet_size >> 11) & 3;
 
 		if (ecomp != NULL)
@@ -517,6 +520,9 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
 		xfer->max_packet_size &= 0x7FF;
 		break;
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_X2:
+	case USB_SPEED_SUPER_PLUS_GEN2_X2:
 		xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
 
 		if (ecomp != NULL)
@@ -3534,6 +3540,9 @@ usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
 		[USB_SPEED_HIGH] = 1024,
 		[USB_SPEED_VARIABLE] = 1024,
 		[USB_SPEED_SUPER] = 1024,
+		[USB_SPEED_SUPER_PLUS] = 1024,
+		[USB_SPEED_SUPER_PLUS_X2] = 1024,
+		[USB_SPEED_SUPER_PLUS_GEN2_X2] = 1024,
 	};
 
 	static const uint16_t isoc_range_max[USB_SPEED_MAX] = {
@@ -3542,6 +3551,9 @@ usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
 		[USB_SPEED_HIGH] = 1024,
 		[USB_SPEED_VARIABLE] = 3584,
 		[USB_SPEED_SUPER] = 1024,
+		[USB_SPEED_SUPER_PLUS] = 1024,
+		[USB_SPEED_SUPER_PLUS_X2] = 1024,
+		[USB_SPEED_SUPER_PLUS_GEN2_X2] = 1024,
 	};
 
 	static const uint16_t control_min[USB_SPEED_MAX] = {
@@ -3550,6 +3562,9 @@ usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
 		[USB_SPEED_HIGH] = 64,
 		[USB_SPEED_VARIABLE] = 512,
 		[USB_SPEED_SUPER] = 512,
+		[USB_SPEED_SUPER_PLUS] = 512,
+		[USB_SPEED_SUPER_PLUS_X2] = 512,
+		[USB_SPEED_SUPER_PLUS_GEN2_X2] = 512,
 	};
 
 	static const uint16_t bulk_min[USB_SPEED_MAX] = {
@@ -3558,6 +3573,9 @@ usbd_get_std_packet_size(struct usb_std_packet_size *ptr,
 		[USB_SPEED_HIGH] = 512,
 		[USB_SPEED_VARIABLE] = 512,
 		[USB_SPEED_SUPER] = 1024,
+		[USB_SPEED_SUPER_PLUS] = 1024,
+		[USB_SPEED_SUPER_PLUS_X2] = 1024,
+		[USB_SPEED_SUPER_PLUS_GEN2_X2] = 1024,
 	};
 
 	uint16_t temp;