diff mbox series

[v3] USB: Extend usb_device_speed with new value USB_SPEED_SUPER_PLUS_BY2

Message ID 20230901160532.6313-1-18500469033@163.com (mailing list archive)
State New, archived
Headers show
Series [v3] USB: Extend usb_device_speed with new value USB_SPEED_SUPER_PLUS_BY2 | expand

Commit Message

Dingyan Li Sept. 1, 2023, 4:05 p.m. UTC
Currently there are there major generations when speaking of
USB_SPEED_SUPER_PLUS devices. However, they actually stands
for different physical speeds. GEN_2x2 means 20Gbps, while
the others mean 10Gbps. So in order to confirm 20Gbps, both
speed and generation need ti be checked. This causes a trouble
for ioctl USBDEVFS_GET_SPEED since it can only return speed
value to userspace.

In order not to add a new ioctl to get ssp generation, extending
usb_device_speed is a good option. The side effect is that
USB_SPEED_SUPER_PLUS has been used in lots of places and
it also takes some effort to go through all of them and check
whether the new speed should be used too.

Besides, as suggested by Alen, ssp_rate is not a proper name,
change it to ssp_gen. And change all functions/struct fileds
ended with ssp_rate to ssp_gen. And there is also some code
refactor to reduce duplicate definition of strings and increase
the utilization of commonly defined utilities.

Signed-off-by: Dingyan Li <18500469033@163.com>
---
 drivers/bluetooth/btusb.c                     |  1 +
 drivers/media/usb/uvc/uvc_video.c             |  1 +
 drivers/net/usb/r8152.c                       |  1 +
 drivers/net/usb/usbnet.c                      |  1 +
 .../broadcom/brcm80211/brcmfmac/usb.c         | 21 +++--
 drivers/phy/tegra/xusb.c                      |  2 +-
 drivers/usb/cdns3/cdnsp-gadget.c              |  3 +
 drivers/usb/cdns3/cdnsp-mem.c                 |  4 +-
 drivers/usb/common/common.c                   | 85 ++++++++++++++++---
 drivers/usb/core/config.c                     |  2 +
 drivers/usb/core/devices.c                    | 14 ++-
 drivers/usb/core/hcd.c                        |  8 +-
 drivers/usb/core/hub.c                        | 32 ++++---
 drivers/usb/core/sysfs.c                      | 24 ++----
 drivers/usb/core/urb.c                        |  3 +-
 drivers/usb/dwc3/core.c                       | 18 ++--
 drivers/usb/dwc3/core.h                       |  4 +-
 drivers/usb/dwc3/gadget.c                     | 58 +++++++------
 drivers/usb/gadget/composite.c                | 12 ++-
 drivers/usb/gadget/configfs.c                 | 22 ++---
 drivers/usb/gadget/function/f_fs.c            |  1 +
 drivers/usb/gadget/function/f_sourcesink.c    |  1 +
 drivers/usb/gadget/function/f_uac2.c          | 14 +--
 drivers/usb/gadget/udc/core.c                 |  4 +-
 drivers/usb/host/xhci-mem.c                   | 17 ++--
 drivers/usb/host/xhci-mtk-sch.c               |  1 +
 drivers/usb/host/xhci.c                       |  7 +-
 drivers/usb/host/xhci.h                       |  5 +-
 drivers/usb/mtu3/mtu3_core.c                  |  2 +
 drivers/usb/mtu3/mtu3_gadget.c                |  1 +
 include/linux/usb.h                           |  2 +-
 include/linux/usb/ch9.h                       | 14 +--
 include/linux/usb/gadget.h                    |  8 +-
 include/uapi/linux/usb/ch9.h                  | 13 ++-
 sound/usb/card.c                              | 15 ++--
 sound/usb/helper.c                            |  1 +
 sound/usb/midi.c                              |  1 +
 tools/usb/testusb.c                           |  6 +-
 38 files changed, 258 insertions(+), 171 deletions(-)

Comments

Thinh Nguyen Sept. 1, 2023, 9:56 p.m. UTC | #1
Hi,

Please Cc me for changes related to dwc3.

On Sat, Sep 02, 2023, Dingyan Li wrote:
> Currently there are there major generations when speaking of
> USB_SPEED_SUPER_PLUS devices. However, they actually stands
> for different physical speeds. GEN_2x2 means 20Gbps, while
> the others mean 10Gbps. So in order to confirm 20Gbps, both
> speed and generation need ti be checked. This causes a trouble
> for ioctl USBDEVFS_GET_SPEED since it can only return speed
> value to userspace.
> 
> In order not to add a new ioctl to get ssp generation, extending
> usb_device_speed is a good option. The side effect is that
> USB_SPEED_SUPER_PLUS has been used in lots of places and
> it also takes some effort to go through all of them and check
> whether the new speed should be used too.
> 
> Besides, as suggested by Alen, ssp_rate is not a proper name,
> change it to ssp_gen. And change all functions/struct fileds
> ended with ssp_rate to ssp_gen. And there is also some code
> refactor to reduce duplicate definition of strings and increase
> the utilization of commonly defined utilities.
> 
> Signed-off-by: Dingyan Li <18500469033@163.com>

Why not spell out the whole thing instead of USB_SPEED_SUPER_PLUS_BY2
(ie. USB_SPEED_SUPER_PLUS_GEN_2x2) as you intended instead of just the
lane count.

There are SuperSpeed Plus generation _and_ lane count. That's why I
didn't name "usb_ssp_gen" that only reflects the generation and not the
lane count. Also, I didn't extend usb_device_speed because gen XxY are
all a single speed: SuperSpeed Plus.

If you're planning to do it this way, why not add the other speeds (such
as gen 1x2) to usb_device_speed enum too? Then we can drop the
usb_ssp_rate enum. If we're going to check multiple enum for SuperSpeed
Plus, we probably need a usb_device_is_superspeed_plus() function.

Now we need to audit all the greater/lesser speed checks that use < or >
to make sure that they are used how they were intended to.

Since these changes are not simple and will touch on multiple places,
please split this patch out.

Thanks,
Thinh
Thinh Nguyen Sept. 1, 2023, 10:33 p.m. UTC | #2
Hi,

Please Cc me for changes related to dwc3.

On Sat, Sep 02, 2023, Dingyan Li wrote:
> Currently there are there major generations when speaking of
> USB_SPEED_SUPER_PLUS devices. However, they actually stands
> for different physical speeds. GEN_2x2 means 20Gbps, while
> the others mean 10Gbps. So in order to confirm 20Gbps, both
> speed and generation need ti be checked. This causes a trouble
> for ioctl USBDEVFS_GET_SPEED since it can only return speed
> value to userspace.
> 
> In order not to add a new ioctl to get ssp generation, extending
> usb_device_speed is a good option. The side effect is that
> USB_SPEED_SUPER_PLUS has been used in lots of places and
> it also takes some effort to go through all of them and check
> whether the new speed should be used too.
> 
> Besides, as suggested by Alen, ssp_rate is not a proper name,
> change it to ssp_gen. And change all functions/struct fileds
> ended with ssp_rate to ssp_gen. And there is also some code
> refactor to reduce duplicate definition of strings and increase
> the utilization of commonly defined utilities.
> 
> Signed-off-by: Dingyan Li <18500469033@163.com>
> ---

Can we spell out the whole thing instead of USB_SPEED_SUPER_PLUS_BY2
(ie. USB_SPEED_SUPER_PLUS_GEN_2x2 as you intended) instead of just the
lane count.

There are SuperSpeed Plus generation _and_ lane count. That's why I
didn't name "usb_ssp_gen" that only reflects the generation and not the
lane count. Also, I didn't extend usb_device_speed because gen XxY are
all a single speed: SuperSpeed Plus.

If you're planning to do it this way, why not add the other speeds (such
as gen 1x2) to usb_device_speed enum too? Then we can drop the
usb_ssp_rate enum. If we're going to check multiple enum for SuperSpeed
Plus, we probably need a usb_device_is_superspeed_plus() function.

Now we need to audit all the greater/lesser speed checks that use < or >
to make sure that they are used how they were intended to.

Since these changes are not simple and will touch on multiple places,
please split this patch out.

Thanks,
Thinh
Dingyan Li Sept. 3, 2023, 9:15 a.m. UTC | #3
At 2023-09-02 06:33:30, "Thinh Nguyen" <Thinh.Nguyen@synopsys.com> wrote:
>Hi,
>
>Please Cc me for changes related to dwc3.
>
Sure, thanks for letting me know.

>On Sat, Sep 02, 2023, Dingyan Li wrote:
>> Currently there are there major generations when speaking of
>> USB_SPEED_SUPER_PLUS devices. However, they actually stands
>> for different physical speeds. GEN_2x2 means 20Gbps, while
>> the others mean 10Gbps. So in order to confirm 20Gbps, both
>> speed and generation need ti be checked. This causes a trouble
>> for ioctl USBDEVFS_GET_SPEED since it can only return speed
>> value to userspace.
>> 
>> In order not to add a new ioctl to get ssp generation, extending
>> usb_device_speed is a good option. The side effect is that
>> USB_SPEED_SUPER_PLUS has been used in lots of places and
>> it also takes some effort to go through all of them and check
>> whether the new speed should be used too.
>> 
>> Besides, as suggested by Alen, ssp_rate is not a proper name,
>> change it to ssp_gen. And change all functions/struct fileds
>> ended with ssp_rate to ssp_gen. And there is also some code
>> refactor to reduce duplicate definition of strings and increase
>> the utilization of commonly defined utilities.
>> 
>> Signed-off-by: Dingyan Li <18500469033@163.com>
>> ---
>
>Can we spell out the whole thing instead of USB_SPEED_SUPER_PLUS_BY2
>(ie. USB_SPEED_SUPER_PLUS_GEN_2x2 as you intended) instead of just the
>lane count.
>
Here is a little bit more context at
https://lore.kernel.org/lkml/07c821ae-2391-474c-aec9-65f47d3fecf2@rowland.harvard.edu/
What I'm trying to do is that in enum usb_device_speed, we only care about
overall speed instead of stuff like lanes. For example, GEN_1x2 and
GEN_2X1 are both 10Gbps, so we can use USB_SPEED_SUPER_PLUS
to represent 10Gbps. GEN_2x2 represent 20Gbps, we can use
USB_SPEED_SUPER_PLUS_BY2. There is no need to append generation
and lane info when we only want to talk about overall speed. By the way,
Apple also uses a similar way to declare speed enums and the new
speed name is kind of borrowed from it.

>There are SuperSpeed Plus generation _and_ lane count. That's why I
>didn't name "usb_ssp_gen" that only reflects the generation and not the
>
Still, I think "usb_ssp_gen" is slightly better than "usb_ssp_rate". As for
the lanes, I think it's OK to not mention it in the name since there are
already comments to explain what this enum is for. Besides, the word
"rate" is kind of like "speed", which should be covered by usb_device_speed
instead of in the enum for generation and lanes.

>lane count. Also, I didn't extend usb_device_speed because gen XxY are
>all a single speed: SuperSpeed Plus.
>
Again, I think it depends on what we really mean when speaking of speed.
Clearly GEN_2x2 and GEN_2x1 have different overall speed. Let's not hide
the fact under SuperSpeed Plus.

>If you're planning to do it this way, why not add the other speeds (such
>as gen 1x2) to usb_device_speed enum too? Then we can drop the
>
Like I said above, if we only care about the overall speed, there is no need
to tell GEN_1x2 from GEN_2x1 since both are 10Gbps. But like in dwc3 code,
there are some different behaviors based on generation and lanes, so
the enum still needs to be kept.

>usb_ssp_rate enum. If we're going to check multiple enum for SuperSpeed
>Plus, we probably need a usb_device_is_superspeed_plus() function.
>
>Now we need to audit all the greater/lesser speed checks that use < or >
>to make sure that they are used how they were intended to.
>
After going through all places where USB_SPEED_SUPER_PLUS is used,
for switch statements, I choose to add  an extra case. For if statement,
change "==" to ">=". But I'm not completely sure they are all correct,
which need to be further checked by maintainers.

>Since these changes are not simple and will touch on multiple places,
>please split this patch out.
>
Okay, I can try to split the patch once we reach an agreement on
how to handle SSP speed and generation. Besides, there is almost
one file for each different module and it's not good to send one patch
for each of them, right? There would be many in this way.

Regards,
Dingyan
Thinh Nguyen Sept. 7, 2023, 12:13 a.m. UTC | #4
On Sun, Sep 03, 2023, Dingyan Li wrote:
> 
> At 2023-09-02 06:33:30, "Thinh Nguyen" <Thinh.Nguyen@synopsys.com> wrote:
> >Hi,
> >
> >Please Cc me for changes related to dwc3.
> >
> Sure, thanks for letting me know.
> 
> >On Sat, Sep 02, 2023, Dingyan Li wrote:
> >> Currently there are there major generations when speaking of
> >> USB_SPEED_SUPER_PLUS devices. However, they actually stands
> >> for different physical speeds. GEN_2x2 means 20Gbps, while
> >> the others mean 10Gbps. So in order to confirm 20Gbps, both
> >> speed and generation need ti be checked. This causes a trouble
> >> for ioctl USBDEVFS_GET_SPEED since it can only return speed
> >> value to userspace.
> >> 
> >> In order not to add a new ioctl to get ssp generation, extending
> >> usb_device_speed is a good option. The side effect is that
> >> USB_SPEED_SUPER_PLUS has been used in lots of places and
> >> it also takes some effort to go through all of them and check
> >> whether the new speed should be used too.
> >> 
> >> Besides, as suggested by Alen, ssp_rate is not a proper name,
> >> change it to ssp_gen. And change all functions/struct fileds
> >> ended with ssp_rate to ssp_gen. And there is also some code
> >> refactor to reduce duplicate definition of strings and increase
> >> the utilization of commonly defined utilities.
> >> 
> >> Signed-off-by: Dingyan Li <18500469033@163.com>
> >> ---
> >
> >Can we spell out the whole thing instead of USB_SPEED_SUPER_PLUS_BY2
> >(ie. USB_SPEED_SUPER_PLUS_GEN_2x2 as you intended) instead of just the
> >lane count.
> >
> Here is a little bit more context at
> https://urldefense.com/v3/__https://lore.kernel.org/lkml/07c821ae-2391-474c-aec9-65f47d3fecf2@rowland.harvard.edu/__;!!A4F2R9G_pg!be_iVrJNFXagks2td2lrjlK6RvWnQ8P8wXkBJwQULZNbVDKcLDOBw_45IPNVe8Lm_i-CU3eq0D4hkPWUNTatmVJIVQ$ 
> What I'm trying to do is that in enum usb_device_speed, we only care about
> overall speed instead of stuff like lanes. For example, GEN_1x2 and
> GEN_2X1 are both 10Gbps, so we can use USB_SPEED_SUPER_PLUS
> to represent 10Gbps. GEN_2x2 represent 20Gbps, we can use
> USB_SPEED_SUPER_PLUS_BY2. There is no need to append generation
> and lane info when we only want to talk about overall speed. By the way,
> Apple also uses a similar way to declare speed enums and the new
> speed name is kind of borrowed from it.

The USB speed naming convention is already confusing as is. Now if you
introduce a new version of calling SuperSpeed Plus Gen 2x2 as
USB_SPEED_SUPER_PLUS_BY2, it's even more confusing.

Probably most class/function drivers don't care about the Gen or lane
count. However, the controller drivers use that to properly configure
the controller and report the speeds. If you really don't care about
the gen and the lane count, we may as well report everything as
SuperSpeed Plus. But that's not the case right? Your use case is that
you only care about 10Gbps or 20Gbps. Why limit to only your use case?

> 
> >There are SuperSpeed Plus generation _and_ lane count. That's why I
> >didn't name "usb_ssp_gen" that only reflects the generation and not the
> >
> Still, I think "usb_ssp_gen" is slightly better than "usb_ssp_rate". As for
> the lanes, I think it's OK to not mention it in the name since there are
> already comments to explain what this enum is for. Besides, the word
> "rate" is kind of like "speed", which should be covered by usb_device_speed
> instead of in the enum for generation and lanes.

Sure, but we could argue that it shares how the usb spec indicates Gen
XxY as where X is the "rate" of signaling on the wire.

But then again, I had trouble coming up with a better name. :/

> 
> >lane count. Also, I didn't extend usb_device_speed because gen XxY are
> >all a single speed: SuperSpeed Plus.
> >
> Again, I think it depends on what we really mean when speaking of speed.
> Clearly GEN_2x2 and GEN_2x1 have different overall speed. Let's not hide
> the fact under SuperSpeed Plus.

Well, the fact is that the current enum USB_SPEED_SUPER_PLUS can no
longer represent just Gen2x1. If we keep this enum USB_SPEED_SUPER_PLUS
in usb_device_speed, then this remains unclear, and you're hiding all
the Gen XxY under the same enum.

We attempted to extend and introduce usb_ssp_rate to help get around
this obscurity.

> 
> >If you're planning to do it this way, why not add the other speeds (such
> >as gen 1x2) to usb_device_speed enum too? Then we can drop the
> >
> Like I said above, if we only care about the overall speed, there is no need
> to tell GEN_1x2 from GEN_2x1 since both are 10Gbps. But like in dwc3 code,
> there are some different behaviors based on generation and lanes, so
> the enum still needs to be kept.

As I've mentioned, if you plan to do it this way, then introduce all the
Gen XxY to usb_device_speed. Otherwise, we now duplicating what the
usb_ssp_rate/gen enum was intended for.

> 
> >usb_ssp_rate enum. If we're going to check multiple enum for SuperSpeed
> >Plus, we probably need a usb_device_is_superspeed_plus() function.
> >
> >Now we need to audit all the greater/lesser speed checks that use < or >
> >to make sure that they are used how they were intended to.
> >
> After going through all places where USB_SPEED_SUPER_PLUS is used,
> for switch statements, I choose to add  an extra case. For if statement,
> change "==" to ">=". But I'm not completely sure they are all correct,
> which need to be further checked by maintainers.

The downside to introducing these enums to usb_device_speed is that we
need to audit all the drivers that checks for USB_SPEED_SUPER_PLUS.

> 
> >Since these changes are not simple and will touch on multiple places,
> >please split this patch out.
> >
> Okay, I can try to split the patch once we reach an agreement on
> how to handle SSP speed and generation. Besides, there is almost
> one file for each different module and it's not good to send one patch
> for each of them, right? There would be many in this way.
> 

Why is it not good? If you separate these changes, then
* You can keep the Acks for the patches that are already reviewed
* The maintainers don't have to review the large patch over and over
* We can keep track of the small changes
* If there's an issue, we don't have to revert the entire thing

Thanks,
Thinh
diff mbox series

Patch

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 764d176e9735..b926e9dbdbb9 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1298,6 +1298,7 @@  static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
 	 * force_poll_sync changes.
 	 */
 	switch (urb->dev->speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:	/* units are 125us */
 		data->intr_interval = usecs_to_jiffies(urb->interval * 125);
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 28dde08ec6c5..ede56f46881f 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1791,6 +1791,7 @@  u16 uvc_endpoint_max_bpi(struct usb_device *dev, struct usb_host_endpoint *ep)
 	switch (dev->speed) {
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
 	default:
 		psize = usb_endpoint_maxp(&ep->desc);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0738baa5b82e..e993ca78df09 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -7066,6 +7066,7 @@  static void r8153_init(struct r8152 *tp)
 	switch (tp->udev->speed) {
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		tp->coalesce = COALESCE_SUPER;
 		break;
 	case USB_SPEED_HIGH:
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 2d14b0d78541..e9032c1cf66b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -366,6 +366,7 @@  void usbnet_update_max_qlen(struct usbnet *dev)
 		break;
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		/*
 		 * Not take default 5ms qlen for super speed HC to
 		 * save memory, and iperf tests show 2.5ms qlen can
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 2178675ae1a4..43571daf3df0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1427,14 +1427,19 @@  brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	devinfo->ifnum = desc->bInterfaceNumber;
 
-	if (usb->speed == USB_SPEED_SUPER_PLUS)
-		brcmf_dbg(USB, "Broadcom super speed plus USB WLAN interface detected\n");
-	else if (usb->speed == USB_SPEED_SUPER)
-		brcmf_dbg(USB, "Broadcom super speed USB WLAN interface detected\n");
-	else if (usb->speed == USB_SPEED_HIGH)
-		brcmf_dbg(USB, "Broadcom high speed USB WLAN interface detected\n");
-	else
-		brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n");
+	switch (usb->speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER:
+	case USB_SPEED_HIGH:
+		brcmf_dbg(USB, "Broadcom %s USB WLAN interface detected\n",
+			  usb_speed_string(usb->speed));
+		break;
+	default:
+		brcmf_dbg(USB, "Broadcom %s USB WLAN interface detected\n",
+			  usb_speed_string(USB_SPEED_FULL));
+		break;
+	}
 
 	ret = brcmf_usb_probe_cb(devinfo, id->driver_info);
 	if (ret)
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index a296b87dced1..2f6d7fee17bd 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -977,7 +977,7 @@  static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3)
 		maximum_speed =  usb_get_maximum_speed(&port->dev);
 		if (maximum_speed == USB_SPEED_SUPER)
 			usb3->disable_gen2 = true;
-		else if (maximum_speed == USB_SPEED_SUPER_PLUS)
+		else if (maximum_speed >= USB_SPEED_SUPER_PLUS)
 			usb3->disable_gen2 = false;
 		else
 			return -EINVAL;
diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c
index fff9ec9c391f..f755b947d7d8 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.c
+++ b/drivers/usb/cdns3/cdnsp-gadget.c
@@ -1250,6 +1250,7 @@  static int cdnsp_run(struct cdnsp_device *pdev,
 	temp = readl(&pdev->port3x_regs->mode_addr);
 
 	switch (speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 		temp |= CFG_3XPORT_SSP_SUPPORT;
 		break;
@@ -1745,6 +1746,7 @@  void cdnsp_irq_reset(struct cdnsp_device *pdev)
 	spin_lock(&pdev->lock);
 
 	switch (pdev->gadget.speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
@@ -1873,6 +1875,7 @@  static int __cdnsp_gadget_init(struct cdns *cdns)
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		break;
 	default:
 		dev_err(cdns->dev, "invalid speed parameter %d\n", max_speed);
diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c
index 97866bfb2da9..9cf3516eb9ce 100644
--- a/drivers/usb/cdns3/cdnsp-mem.c
+++ b/drivers/usb/cdns3/cdnsp-mem.c
@@ -736,6 +736,7 @@  int cdnsp_setup_addressable_priv_dev(struct cdnsp_device *pdev)
 	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
 
 	switch (pdev->gadget.speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP);
 		max_packets = MAX_PACKET(512);
@@ -833,8 +834,9 @@  static unsigned int cdnsp_get_endpoint_interval(struct usb_gadget *g,
 
 	switch (g->speed) {
 	case USB_SPEED_HIGH:
-	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		if (usb_endpoint_xfer_int(pep->endpoint.desc) ||
 		    usb_endpoint_xfer_isoc(pep->endpoint.desc))
 			interval = cdnsp_parse_exponent_interval(g, pep);
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index b84efae26e15..41bd032fc139 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -67,22 +67,35 @@  const char *usb_otg_state_string(enum usb_otg_state state)
 EXPORT_SYMBOL_GPL(usb_otg_state_string);
 
 static const char *const speed_names[] = {
-	[USB_SPEED_UNKNOWN] = "UNKNOWN",
+	[USB_SPEED_UNKNOWN] = "unknown-speed",
 	[USB_SPEED_LOW] = "low-speed",
 	[USB_SPEED_FULL] = "full-speed",
 	[USB_SPEED_HIGH] = "high-speed",
 	[USB_SPEED_WIRELESS] = "wireless",
 	[USB_SPEED_SUPER] = "super-speed",
 	[USB_SPEED_SUPER_PLUS] = "super-speed-plus",
+	[USB_SPEED_SUPER_PLUS_BY2] = "super-speed-plus-by2",
 };
 
-static const char *const ssp_rate[] = {
-	[USB_SSP_GEN_UNKNOWN] = "UNKNOWN",
+static const char *const ssp_gen_names[] = {
+	[USB_SSP_GEN_UNKNOWN] = "super-speed-plus-gen-unknown",
 	[USB_SSP_GEN_2x1] = "super-speed-plus-gen2x1",
 	[USB_SSP_GEN_1x2] = "super-speed-plus-gen1x2",
 	[USB_SSP_GEN_2x2] = "super-speed-plus-gen2x2",
 };
 
+/* Mbps */
+static const char *const speed_values[] = {
+	[USB_SPEED_UNKNOWN] = "unknown-value",
+	[USB_SPEED_LOW] = "1.5",
+	[USB_SPEED_FULL] = "12",
+	[USB_SPEED_HIGH] = "480",
+	[USB_SPEED_WIRELESS] = "480",
+	[USB_SPEED_SUPER] = "5000",
+	[USB_SPEED_SUPER_PLUS] = "10000",
+	[USB_SPEED_SUPER_PLUS_BY2] = "20000",
+};
+
 /**
  * usb_speed_string() - Returns human readable-name of the speed.
  * @speed: The speed to return human-readable name for.  If it's not
@@ -97,6 +110,56 @@  const char *usb_speed_string(enum usb_device_speed speed)
 }
 EXPORT_SYMBOL_GPL(usb_speed_string);
 
+/**
+ * usb_speed_value() - Returns human readable speed value.
+ * @speed: The speed to return human-readable value for. If it's not
+ *   any of the speeds defined in usb_device_speed enum, value for
+ *   USB_SPEED_UNKNOWN will be returned.
+ */
+const char *usb_speed_value(enum usb_device_speed speed)
+{
+	if (speed < 0 || speed >= ARRAY_SIZE(speed_values))
+		speed = USB_SPEED_UNKNOWN;
+	return speed_values[speed];
+}
+EXPORT_SYMBOL_GPL(usb_speed_value);
+
+/**
+ * usb_ssp_gen_name() - Returns human readable-name of ssp generation.
+ * @gen: The ssp generation to return human-readable name for. If it's
+ *   not any of the values defined in usb_ssp_gen enum, name for
+ *   USB_SSP_GEN_UNKNOWN will be returned.
+ */
+const char *usb_ssp_gen_name(enum usb_ssp_gen gen)
+{
+	if (gen < 0 || gen >= ARRAY_SIZE(ssp_gen_names))
+		gen = USB_SSP_GEN_UNKNOWN;
+	return ssp_gen_names[gen];
+}
+EXPORT_SYMBOL_GPL(usb_ssp_gen_name);
+
+/**
+ * usb_speed_from_name() - Returns usb_device_speed enum from human
+ * readable name.
+ * @speed_name: The speed name to return usb_device_speed enum for,
+ *   which can be defined in speed_names or ssp_gen_names. USB_SPEED_UNKNOWN
+ *   will be returned if the name can't be recognized.
+ */
+enum usb_device_speed usb_speed_from_name(const char *speed_name)
+{
+	int ret;
+
+	ret = match_string(ssp_gen_names, ARRAY_SIZE(ssp_gen_names), speed_name);
+	if (ret == USB_SSP_GEN_2x2)
+		return USB_SPEED_SUPER_PLUS_BY2;
+	else if (ret > 0)
+		return USB_SPEED_SUPER_PLUS;
+
+	ret = match_string(speed_names, ARRAY_SIZE(speed_names), speed_name);
+	return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
+}
+EXPORT_SYMBOL_GPL(usb_speed_from_name);
+
 /**
  * usb_get_maximum_speed - Get maximum requested speed for a given USB
  * controller.
@@ -114,25 +177,21 @@  enum usb_device_speed usb_get_maximum_speed(struct device *dev)
 	if (ret < 0)
 		return USB_SPEED_UNKNOWN;
 
-	ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed);
-	if (ret > 0)
-		return USB_SPEED_SUPER_PLUS;
+	return usb_speed_from_name(maximum_speed);
 
-	ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
-	return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
 }
 EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
 
 /**
- * usb_get_maximum_ssp_rate - Get the signaling rate generation and lane count
+ * usb_get_maximum_ssp_gen - Get the SSP signaling generation and lane count
  *	of a SuperSpeed Plus capable device.
  * @dev: Pointer to the given USB controller device
  *
  * If the string from "maximum-speed" property is super-speed-plus-genXxY where
  * 'X' is the generation number and 'Y' is the number of lanes, then this
- * function returns the corresponding enum usb_ssp_rate.
+ * function returns the corresponding enum usb_ssp_gen.
  */
-enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)
+enum usb_ssp_gen usb_get_maximum_ssp_gen(struct device *dev)
 {
 	const char *maximum_speed;
 	int ret;
@@ -141,10 +200,10 @@  enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)
 	if (ret < 0)
 		return USB_SSP_GEN_UNKNOWN;
 
-	ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed);
+	ret = match_string(ssp_gen_names, ARRAY_SIZE(ssp_gen_names), maximum_speed);
 	return (ret < 0) ? USB_SSP_GEN_UNKNOWN : ret;
 }
-EXPORT_SYMBOL_GPL(usb_get_maximum_ssp_rate);
+EXPORT_SYMBOL_GPL(usb_get_maximum_ssp_gen);
 
 /**
  * usb_state_string - Returns human readable name for the state.
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index b19e38d5fd10..71708ee7190c 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -323,6 +323,7 @@  static int usb_parse_endpoint(struct device *ddev, int cfgno,
 	if (usb_endpoint_xfer_int(d)) {
 		i = 1;
 		switch (udev->speed) {
+		case USB_SPEED_SUPER_PLUS_BY2:
 		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:
 		case USB_SPEED_HIGH:
@@ -433,6 +434,7 @@  static int usb_parse_endpoint(struct device *ddev, int cfgno,
 		break;
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		maxpacket_maxes = super_speed_maxpacket_maxes;
 		break;
 	}
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a247da73f34d..62ab4dfa9a51 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -395,7 +395,8 @@  static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
 	int chix;
 	int ret, cnt = 0;
 	int parent_devnum = 0;
-	char *pages_start, *data_end, *speed;
+	char *pages_start, *data_end;
+	const char *speed;
 	unsigned int length;
 	ssize_t total_written = 0;
 	struct usb_device *childdev = NULL;
@@ -419,19 +420,16 @@  static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
 	 * plugged into the root hub has a parent of 0.
 	 */
 	switch (usbdev->speed) {
-	case USB_SPEED_LOW:
-		speed = "1.5"; break;
 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
-	case USB_SPEED_FULL:
 		speed = "12"; break;
+	case USB_SPEED_LOW:
+	case USB_SPEED_FULL:
 	case USB_SPEED_HIGH:
-		speed = "480"; break;
 	case USB_SPEED_SUPER:
-		speed = "5000"; break;
 	case USB_SPEED_SUPER_PLUS:
-		speed = "10000"; break;
+	case USB_SPEED_SUPER_PLUS_BY2:
 	default:
-		speed = "??";
+		speed = usb_speed_value(usbdev->speed); break;
 	}
 	data_end = pages_start + sprintf(pages_start, format_topo,
 			bus->busnum, level, parent_devnum,
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12b6dfeaf658..315bb6887a06 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2865,7 +2865,7 @@  int usb_add_hcd(struct usb_hcd *hcd,
 
 	rhdev->rx_lanes = 1;
 	rhdev->tx_lanes = 1;
-	rhdev->ssp_rate = USB_SSP_GEN_UNKNOWN;
+	rhdev->ssp_gen = USB_SSP_GEN_UNKNOWN;
 
 	switch (hcd->speed) {
 	case HCD_USB11:
@@ -2880,11 +2880,11 @@  int usb_add_hcd(struct usb_hcd *hcd,
 	case HCD_USB32:
 		rhdev->rx_lanes = 2;
 		rhdev->tx_lanes = 2;
-		rhdev->ssp_rate = USB_SSP_GEN_2x2;
-		rhdev->speed = USB_SPEED_SUPER_PLUS;
+		rhdev->ssp_gen = USB_SSP_GEN_2x2;
+		rhdev->speed = USB_SPEED_SUPER_PLUS_BY2;
 		break;
 	case HCD_USB31:
-		rhdev->ssp_rate = USB_SSP_GEN_2x1;
+		rhdev->ssp_gen = USB_SSP_GEN_2x1;
 		rhdev->speed = USB_SPEED_SUPER_PLUS;
 		break;
 	default:
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3c54b218301c..76eb864f939c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2693,16 +2693,16 @@  int usb_authorize_device(struct usb_device *usb_dev)
 }
 
 /**
- * get_port_ssp_rate - Match the extended port status to SSP rate
+ * get_port_ssp_gen - Match the extended port status to SSP generation
  * @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.
+ * return the corresponding enum usb_ssp_gen.
  */
-static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev,
-					   u32 ext_portstatus)
+static enum usb_ssp_gen get_port_ssp_gen(struct usb_device *hdev,
+					  u32 ext_portstatus)
 {
 	struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap;
 	u32 attr;
@@ -2913,13 +2913,15 @@  static int hub_port_wait_reset(struct usb_hub *hub, int port1,
 		/* extended portstatus Rx and Tx lane count are zero based */
 		udev->rx_lanes = USB_EXT_PORT_RX_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);
+		udev->ssp_gen = get_port_ssp_gen(hub->hdev, ext_portstatus);
 	} else {
 		udev->rx_lanes = 1;
 		udev->tx_lanes = 1;
-		udev->ssp_rate = USB_SSP_GEN_UNKNOWN;
+		udev->ssp_gen = USB_SSP_GEN_UNKNOWN;
 	}
-	if (udev->ssp_rate != USB_SSP_GEN_UNKNOWN)
+	if (udev->ssp_gen == USB_SSP_GEN_2x2)
+		udev->speed = USB_SPEED_SUPER_PLUS_BY2;
+	else if (udev->ssp_gen != USB_SSP_GEN_UNKNOWN)
 		udev->speed = USB_SPEED_SUPER_PLUS;
 	else if (hub_is_superspeed(hub->hdev))
 		udev->speed = USB_SPEED_SUPER;
@@ -4830,6 +4832,7 @@  hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
 		 * it's fixed size except for full speed devices.
 		 */
 		switch (udev->speed) {
+		case USB_SPEED_SUPER_PLUS_BY2:
 		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:
 			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
@@ -4960,16 +4963,11 @@  hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
 		if (udev->speed >= USB_SPEED_SUPER) {
 			devnum = udev->devnum;
 			dev_info(&udev->dev,
-					"%s SuperSpeed%s%s USB device number %d using %s\n",
-					(udev->config) ? "reset" : "new",
-				 (udev->speed == USB_SPEED_SUPER_PLUS) ?
-						" Plus" : "",
-				 (udev->ssp_rate == USB_SSP_GEN_2x2) ?
-						" Gen 2x2" :
-				 (udev->ssp_rate == USB_SSP_GEN_2x1) ?
-						" Gen 2x1" :
-				 (udev->ssp_rate == USB_SSP_GEN_1x2) ?
-						" Gen 1x2" : "",
+				 "%s %s USB device number %d using %s\n",
+				 (udev->config) ? "reset" : "new",
+				 (udev->speed == USB_SPEED_SUPER) ?
+					usb_speed_string(USB_SPEED_SUPER) :
+					usb_ssp_gen_name(udev->ssp_gen),
 				 devnum, driver_name);
 		}
 
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 5d21718afb05..121c94fd3599 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -146,32 +146,21 @@  static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
 	struct usb_device *udev;
-	char *speed;
+	const char *speed;
 
 	udev = to_usb_device(dev);
 
 	switch (udev->speed) {
-	case USB_SPEED_LOW:
-		speed = "1.5";
-		break;
 	case USB_SPEED_UNKNOWN:
+		speed = "12"; break;
+	case USB_SPEED_LOW:
 	case USB_SPEED_FULL:
-		speed = "12";
-		break;
 	case USB_SPEED_HIGH:
-		speed = "480";
-		break;
 	case USB_SPEED_SUPER:
-		speed = "5000";
-		break;
 	case USB_SPEED_SUPER_PLUS:
-		if (udev->ssp_rate == USB_SSP_GEN_2x2)
-			speed = "20000";
-		else
-			speed = "10000";
-		break;
+	case USB_SPEED_SUPER_PLUS_BY2:
 	default:
-		speed = "unknown";
+		speed = usb_speed_value(udev->speed); break;
 	}
 	return sysfs_emit(buf, "%s\n", speed);
 }
@@ -656,8 +645,7 @@  static int add_power_attributes(struct device *dev)
 		if (udev->usb2_hw_lpm_capable == 1)
 			rc = sysfs_merge_group(&dev->kobj,
 					&usb2_hardware_lpm_attr_group);
-		if ((udev->speed == USB_SPEED_SUPER ||
-		     udev->speed == USB_SPEED_SUPER_PLUS) &&
+		if (udev->speed >= USB_SPEED_SUPER &&
 				udev->lpm_capable == 1)
 			rc = sysfs_merge_group(&dev->kobj,
 					&usb3_hardware_lpm_attr_group);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 7576920e2d5a..d90df1ca050c 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -459,7 +459,7 @@  int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 			max *= mult;
 		}
 
-		if (dev->speed == USB_SPEED_SUPER_PLUS &&
+		if (dev->speed >= USB_SPEED_SUPER_PLUS &&
 		    USB_SS_SSP_ISOC_COMP(ep->ss_ep_comp.bmAttributes)) {
 			struct usb_ssp_isoc_ep_comp_descriptor *isoc_ep_comp;
 
@@ -544,6 +544,7 @@  int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 
 		/* too big? */
 		switch (dev->speed) {
+		case USB_SPEED_SUPER_PLUS_BY2:
 		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:	/* units are 125us */
 			/* Handle up to 2^(16-1) microframes */
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9c6bf054f15d..70ac85ad192d 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1408,7 +1408,7 @@  static void dwc3_get_properties(struct dwc3 *dwc)
 	tx_fifo_resize_max_num = 6;
 
 	dwc->maximum_speed = usb_get_maximum_speed(dev);
-	dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
+	dwc->max_ssp_gen = usb_get_maximum_ssp_gen(dev);
 	dwc->dr_mode = usb_get_dr_mode(dev);
 	dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
 
@@ -1575,6 +1575,7 @@  static void dwc3_check_params(struct dwc3 *dwc)
 			dev_warn(dev, "UDC doesn't support Gen 1\n");
 		break;
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		if ((DWC3_IP_IS(DWC32) &&
 		     hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) ||
 		    (!DWC3_IP_IS(DWC32) &&
@@ -1613,8 +1614,8 @@  static void dwc3_check_params(struct dwc3 *dwc)
 	 * set the default to support dual-lane for DWC_usb32 and single-lane
 	 * for DWC_usb31 for super-speed-plus.
 	 */
-	if (dwc->maximum_speed == USB_SPEED_SUPER_PLUS) {
-		switch (dwc->max_ssp_rate) {
+	if (dwc->maximum_speed >= USB_SPEED_SUPER_PLUS) {
+		switch (dwc->max_ssp_gen) {
 		case USB_SSP_GEN_2x1:
 			if (hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_GEN1)
 				dev_warn(dev, "UDC only supports Gen 1\n");
@@ -1628,14 +1629,15 @@  static void dwc3_check_params(struct dwc3 *dwc)
 		default:
 			switch (hwparam_gen) {
 			case DWC3_GHWPARAMS3_SSPHY_IFC_GEN2:
-				if (DWC3_IP_IS(DWC32))
-					dwc->max_ssp_rate = USB_SSP_GEN_2x2;
-				else
-					dwc->max_ssp_rate = USB_SSP_GEN_2x1;
+				if (DWC3_IP_IS(DWC32)) {
+					dwc->max_ssp_gen = USB_SSP_GEN_2x2;
+					dwc->maximum_speed = USB_SPEED_SUPER_PLUS_BY2;
+				} else
+					dwc->max_ssp_gen = USB_SSP_GEN_2x1;
 				break;
 			case DWC3_GHWPARAMS3_SSPHY_IFC_GEN1:
 				if (DWC3_IP_IS(DWC32))
-					dwc->max_ssp_rate = USB_SSP_GEN_1x2;
+					dwc->max_ssp_gen = USB_SSP_GEN_1x2;
 				break;
 			}
 			break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index a69ac67d89fe..414be70633df 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1194,8 +1194,8 @@  struct dwc3 {
 	u32			u1u2;
 	u32			maximum_speed;
 	u32			gadget_max_speed;
-	enum usb_ssp_rate	max_ssp_rate;
-	enum usb_ssp_rate	gadget_ssp_rate;
+	enum usb_ssp_gen	max_ssp_gen;
+	enum usb_ssp_gen	gadget_ssp_gen;
 
 	u32			ip;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 858fe4c299b7..a9998ea731b8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2498,23 +2498,23 @@  static void dwc3_stop_active_transfers(struct dwc3 *dwc)
 
 static void __dwc3_gadget_set_ssp_rate(struct dwc3 *dwc)
 {
-	enum usb_ssp_rate	ssp_rate = dwc->gadget_ssp_rate;
+	enum usb_ssp_gen	ssp_gen = dwc->gadget_ssp_gen;
 	u32			reg;
 
-	if (ssp_rate == USB_SSP_GEN_UNKNOWN)
-		ssp_rate = dwc->max_ssp_rate;
+	if (ssp_gen == USB_SSP_GEN_UNKNOWN)
+		ssp_gen = dwc->max_ssp_gen;
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg &= ~DWC3_DCFG_SPEED_MASK;
 	reg &= ~DWC3_DCFG_NUMLANES(~0);
 
-	if (ssp_rate == USB_SSP_GEN_1x2)
+	if (ssp_gen == USB_SSP_GEN_1x2)
 		reg |= DWC3_DCFG_SUPERSPEED;
-	else if (dwc->max_ssp_rate != USB_SSP_GEN_1x2)
+	else if (dwc->max_ssp_gen != USB_SSP_GEN_1x2)
 		reg |= DWC3_DCFG_SUPERSPEED_PLUS;
 
-	if (ssp_rate != USB_SSP_GEN_2x1 &&
-	    dwc->max_ssp_rate != USB_SSP_GEN_2x1)
+	if (ssp_gen != USB_SSP_GEN_2x1 &&
+	    dwc->max_ssp_gen != USB_SSP_GEN_2x1)
 		reg |= DWC3_DCFG_NUMLANES(1);
 
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
@@ -2529,7 +2529,7 @@  static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
 	if (speed == USB_SPEED_UNKNOWN || speed > dwc->maximum_speed)
 		speed = dwc->maximum_speed;
 
-	if (speed == USB_SPEED_SUPER_PLUS &&
+	if (speed >= USB_SPEED_SUPER_PLUS &&
 	    DWC3_IP_IS(DWC32)) {
 		__dwc3_gadget_set_ssp_rate(dwc);
 		return;
@@ -2566,6 +2566,7 @@  static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
 			reg |= DWC3_DCFG_SUPERSPEED;
 			break;
 		case USB_SPEED_SUPER_PLUS:
+		case USB_SPEED_SUPER_PLUS_BY2:
 			if (DWC3_IP_IS(DWC3))
 				reg |= DWC3_DCFG_SUPERSPEED;
 			else
@@ -3028,15 +3029,22 @@  static void dwc3_gadget_set_speed(struct usb_gadget *g,
 	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
-static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g,
-				     enum usb_ssp_rate rate)
+static void dwc3_gadget_set_ssp_gen(struct usb_gadget *g,
+				    enum usb_ssp_gen gen)
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	unsigned long		flags;
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS;
-	dwc->gadget_ssp_rate = rate;
+	switch (gen) {
+	case USB_SSP_GEN_2x2:
+		dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS_BY2;
+		break;
+	default:
+		dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS;
+		break;
+	}
+	dwc->gadget_ssp_gen = gen;
 	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
@@ -3123,7 +3131,7 @@  static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.udc_start		= dwc3_gadget_start,
 	.udc_stop		= dwc3_gadget_stop,
 	.udc_set_speed		= dwc3_gadget_set_speed,
-	.udc_set_ssp_rate	= dwc3_gadget_set_ssp_rate,
+	.udc_set_ssp_gen	= dwc3_gadget_set_ssp_gen,
 	.get_config_params	= dwc3_gadget_config_params,
 	.vbus_draw		= dwc3_gadget_vbus_draw,
 	.check_config		= dwc3_gadget_check_config,
@@ -4071,7 +4079,7 @@  static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 	if (DWC3_IP_IS(DWC32))
 		lanes = DWC3_DSTS_CONNLANES(reg) + 1;
 
-	dwc->gadget->ssp_rate = USB_SSP_GEN_UNKNOWN;
+	dwc->gadget->ssp_gen = USB_SSP_GEN_UNKNOWN;
 
 	/*
 	 * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed
@@ -4086,12 +4094,14 @@  static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 	case DWC3_DSTS_SUPERSPEED_PLUS:
 		dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 		dwc->gadget->ep0->maxpacket = 512;
-		dwc->gadget->speed = USB_SPEED_SUPER_PLUS;
 
-		if (lanes > 1)
-			dwc->gadget->ssp_rate = USB_SSP_GEN_2x2;
-		else
-			dwc->gadget->ssp_rate = USB_SSP_GEN_2x1;
+		if (lanes > 1) {
+			dwc->gadget->ssp_gen = USB_SSP_GEN_2x2;
+			dwc->gadget->speed = USB_SPEED_SUPER_PLUS_BY2;
+		} else {
+			dwc->gadget->ssp_gen = USB_SSP_GEN_2x1;
+			dwc->gadget->speed = USB_SPEED_SUPER_PLUS;
+		}
 		break;
 	case DWC3_DSTS_SUPERSPEED:
 		/*
@@ -4116,7 +4126,7 @@  static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 
 		if (lanes > 1) {
 			dwc->gadget->speed = USB_SPEED_SUPER_PLUS;
-			dwc->gadget->ssp_rate = USB_SSP_GEN_1x2;
+			dwc->gadget->ssp_gen = USB_SSP_GEN_1x2;
 		}
 		break;
 	case DWC3_DSTS_HIGHSPEED:
@@ -4592,7 +4602,7 @@  int dwc3_gadget_init(struct dwc3 *dwc)
 	dev->platform_data		= dwc;
 	dwc->gadget->ops		= &dwc3_gadget_ops;
 	dwc->gadget->speed		= USB_SPEED_UNKNOWN;
-	dwc->gadget->ssp_rate		= USB_SSP_GEN_UNKNOWN;
+	dwc->gadget->ssp_gen		= USB_SSP_GEN_UNKNOWN;
 	dwc->gadget->sg_supported	= true;
 	dwc->gadget->name		= "dwc3-gadget";
 	dwc->gadget->lpm_capable	= !dwc->usb2_gadget_lpm_disable;
@@ -4620,7 +4630,7 @@  int dwc3_gadget_init(struct dwc3 *dwc)
 				dwc->revision);
 
 	dwc->gadget->max_speed		= dwc->maximum_speed;
-	dwc->gadget->max_ssp_rate	= dwc->max_ssp_rate;
+	dwc->gadget->max_ssp_gen	= dwc->max_ssp_gen;
 
 	/*
 	 * REVISIT: Here we should clear all pending IRQs to be
@@ -4637,8 +4647,8 @@  int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err5;
 	}
 
-	if (DWC3_IP_IS(DWC32) && dwc->maximum_speed == USB_SPEED_SUPER_PLUS)
-		dwc3_gadget_set_ssp_rate(dwc->gadget, dwc->max_ssp_rate);
+	if (DWC3_IP_IS(DWC32) && dwc->maximum_speed >= USB_SPEED_SUPER_PLUS)
+		dwc3_gadget_set_ssp_gen(dwc->gadget, dwc->max_ssp_gen);
 	else
 		dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
 
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 0ace45b66a31..17f3b5e968a7 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -71,6 +71,7 @@  function_descriptors(struct usb_function *f,
 	 */
 
 	switch (speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 		descriptors = f->ssp_descriptors;
 		if (descriptors)
@@ -169,6 +170,7 @@  int config_ep_by_speed_and_alt(struct usb_gadget *g,
 
 	/* select desired speed */
 	switch (g->speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 		if (f->ssp_descriptors) {
 			speed_desc = f->ssp_descriptors;
@@ -650,6 +652,7 @@  static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 check_config:
 		/* ignore configs that won't work at this speed */
 		switch (speed) {
+		case USB_SPEED_SUPER_PLUS_BY2:
 		case USB_SPEED_SUPER_PLUS:
 			if (!c->superspeed_plus)
 				continue;
@@ -688,8 +691,9 @@  static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 			hs = 1;
 		if (gadget->speed == USB_SPEED_SUPER)
 			ss = 1;
-		if (gadget->speed == USB_SPEED_SUPER_PLUS)
+		if (gadget->speed >= USB_SPEED_SUPER_PLUS)
 			ssp = 1;
+
 		if (type == USB_DT_DEVICE_QUALIFIER)
 			hs = !hs;
 	}
@@ -803,7 +807,7 @@  static int bos_desc(struct usb_composite_dev *cdev)
 		u8 ssic;
 		int i;
 
-		if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x2)
+		if (cdev->gadget->max_ssp_gen == USB_SSP_GEN_2x2)
 			ssac = 3;
 
 		/*
@@ -850,8 +854,8 @@  static int bos_desc(struct usb_composite_dev *cdev)
 
 			ssid = i >> 1;
 
-			if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x1 ||
-			    cdev->gadget->max_ssp_rate == USB_SSP_GEN_UNKNOWN)
+			if (cdev->gadget->max_ssp_gen == USB_SSP_GEN_2x1 ||
+			    cdev->gadget->max_ssp_gen == USB_SSP_GEN_UNKNOWN)
 				mantissa = 10;
 			else
 				mantissa = 5 << ssid;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 4c639e9ddedc..e85853bdacf7 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -327,18 +327,18 @@  static ssize_t gadget_dev_desc_max_speed_store(struct config_item *item,
 	if (gi->composite.gadget_driver.udc_name)
 		goto err;
 
-	if (strncmp(page, "super-speed-plus", 16) == 0)
-		gi->composite.max_speed = USB_SPEED_SUPER_PLUS;
-	else if (strncmp(page, "super-speed", 11) == 0)
-		gi->composite.max_speed = USB_SPEED_SUPER;
-	else if (strncmp(page, "high-speed", 10) == 0)
-		gi->composite.max_speed = USB_SPEED_HIGH;
-	else if (strncmp(page, "full-speed", 10) == 0)
-		gi->composite.max_speed = USB_SPEED_FULL;
-	else if (strncmp(page, "low-speed", 9) == 0)
-		gi->composite.max_speed = USB_SPEED_LOW;
-	else
+	gi->composite.max_speed = usb_speed_from_name(page);
+	switch (gi->composite.max_speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
+	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER:
+	case USB_SPEED_HIGH:
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+		break;
+	default:
 		goto err;
+	}
 
 	gi->composite.gadget_driver.max_speed = gi->composite.max_speed;
 
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index f41a385a5c42..56e7b924f3c9 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1321,6 +1321,7 @@  static long ffs_epfile_ioctl(struct file *file, unsigned code,
 		switch (epfile->ffs->gadget->speed) {
 		case USB_SPEED_SUPER:
 		case USB_SPEED_SUPER_PLUS:
+		case USB_SPEED_SUPER_PLUS_BY2:
 			desc_idx = 2;
 			break;
 		case USB_SPEED_HIGH:
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index 2edbd9b510d6..e9bc2b9a1542 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -582,6 +582,7 @@  static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
 
 	if (is_iso) {
 		switch (speed) {
+		case USB_SPEED_SUPER_PLUS_BY2:
 		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:
 			size = ss->isoc_maxpacket *
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 0219cd79493a..0937f55c9c88 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -124,16 +124,6 @@  static struct usb_string strings_fn[] = {
 	{ },
 };
 
-static const char *const speed_names[] = {
-	[USB_SPEED_UNKNOWN] = "UNKNOWN",
-	[USB_SPEED_LOW] = "LS",
-	[USB_SPEED_FULL] = "FS",
-	[USB_SPEED_HIGH] = "HS",
-	[USB_SPEED_WIRELESS] = "W",
-	[USB_SPEED_SUPER] = "SS",
-	[USB_SPEED_SUPER_PLUS] = "SS+",
-};
-
 static struct usb_gadget_strings str_fn = {
 	.language = 0x0409,	/* en-us */
 	.strings = strings_fn,
@@ -763,11 +753,11 @@  static int set_ep_max_packet_size_bint(struct device *dev, const struct f_uac2_o
 	if (max_size_bw <= max_size_ep)
 		dev_dbg(dev,
 			"%s %s: Would use wMaxPacketSize %d and bInterval %d\n",
-			speed_names[speed], dir, max_size_bw, bint);
+			usb_speed_string(speed), dir, max_size_bw, bint);
 	else {
 		dev_warn(dev,
 			"%s %s: Req. wMaxPacketSize %d at bInterval %d > max ISOC %d, may drop data!\n",
-			speed_names[speed], dir, max_size_bw, bint, max_size_ep);
+			usb_speed_string(speed), dir, max_size_bw, bint, max_size_ep);
 		max_size_bw = max_size_ep;
 	}
 
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 7166d1117742..93773f60939b 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1266,8 +1266,8 @@  static inline void usb_gadget_udc_set_speed(struct usb_udc *udc,
 	else
 		s = min(speed, gadget->max_speed);
 
-	if (s == USB_SPEED_SUPER_PLUS && gadget->ops->udc_set_ssp_rate)
-		gadget->ops->udc_set_ssp_rate(gadget, gadget->max_ssp_rate);
+	if (s >= USB_SPEED_SUPER_PLUS && gadget->ops->udc_set_ssp_gen)
+		gadget->ops->udc_set_ssp_gen(gadget, gadget->max_ssp_gen);
 	else if (gadget->ops->udc_set_speed)
 		gadget->ops->udc_set_speed(gadget, s);
 }
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 8714ab5bf04d..e26384b24aa6 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1087,25 +1087,31 @@  int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 	/* 3) Only the control endpoint is valid - one endpoint context */
 	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
 	switch (udev->speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
-		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP);
+		slot_ctx->dev_info |= (xhci->hci_version < 0x120) ?
+					cpu_to_le32(SLOT_SPEED_SSP) : 0;
 		max_packets = MAX_PACKET(512);
 		break;
 	case USB_SPEED_SUPER:
-		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
+		slot_ctx->dev_info |= (xhci->hci_version < 0x120) ?
+					cpu_to_le32(SLOT_SPEED_SS) : 0;
 		max_packets = MAX_PACKET(512);
 		break;
 	case USB_SPEED_HIGH:
-		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS);
+		slot_ctx->dev_info |= (xhci->hci_version < 0x120) ?
+					cpu_to_le32(SLOT_SPEED_HS) : 0;
 		max_packets = MAX_PACKET(64);
 		break;
 	/* USB core guesses at a 64-byte max packet first for FS devices */
 	case USB_SPEED_FULL:
-		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS);
+		slot_ctx->dev_info |= (xhci->hci_version < 0x120) ?
+					cpu_to_le32(SLOT_SPEED_FS) : 0;
 		max_packets = MAX_PACKET(64);
 		break;
 	case USB_SPEED_LOW:
-		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS);
+		slot_ctx->dev_info |= (xhci->hci_version < 0x120) ?
+					cpu_to_le32(SLOT_SPEED_LS) : 0;
 		max_packets = MAX_PACKET(8);
 		break;
 	default:
@@ -1276,6 +1282,7 @@  static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
 		}
 		fallthrough;	/* SS and HS isoc/int have same decoding */
 
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		if (usb_endpoint_xfer_int(&ep->desc) ||
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 579899eb24c1..97318537612a 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -89,6 +89,7 @@  static u32 get_bw_boundary(enum usb_device_speed speed)
 	u32 boundary;
 
 	switch (speed) {
+	case USB_SPEED_SUPER_PLUS_BY2:
 	case USB_SPEED_SUPER_PLUS:
 		boundary = SSP_BW_BOUNDARY;
 		break;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e1b1b64a0723..5483920a6ce9 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2192,6 +2192,7 @@  static unsigned int xhci_get_block_size(struct usb_device *udev)
 		return HS_BLOCK;
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		return SS_BLOCK;
 	case USB_SPEED_UNKNOWN:
 	default:
@@ -5102,15 +5103,15 @@  static void xhci_hcd_init_usb3_data(struct xhci_hcd *xhci, struct usb_hcd *hcd)
 	switch (minor_rev) {
 	case 2:
 		hcd->speed = HCD_USB32;
-		hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
+		hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS_BY2;
 		hcd->self.root_hub->rx_lanes = 2;
 		hcd->self.root_hub->tx_lanes = 2;
-		hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2;
+		hcd->self.root_hub->ssp_gen = USB_SSP_GEN_2x2;
 		break;
 	case 1:
 		hcd->speed = HCD_USB31;
 		hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
-		hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1;
+		hcd->self.root_hub->ssp_gen = USB_SSP_GEN_2x1;
 		break;
 	}
 	xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n",
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7e282b4522c0..ec507770a559 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -345,7 +345,10 @@  struct xhci_op_regs {
 #define DEV_SUPERSPEED_ANY(p)	(((p) & DEV_SPEED_MASK) >= XDEV_SS)
 #define DEV_PORT_SPEED(p)	(((p) >> 10) & 0x0f)
 
-/* Bits 20:23 in the Slot Context are the speed for the device */
+/* Bits 20:23 in the Slot Context are the speed for the device.
+ * This field has been deprecated since xHCI spec revision 1.2
+ * and shall be reserved.
+ */
 #define	SLOT_SPEED_FS		(XDEV_FS << 10)
 #define	SLOT_SPEED_LS		(XDEV_LS << 10)
 #define	SLOT_SPEED_HS		(XDEV_HS << 10)
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index a3a6282893d0..346df653a1e4 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -254,6 +254,7 @@  static void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed)
 			     SSUSB_U3_PORT_SSP_SPEED);
 		break;
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
 		mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0),
 			     SSUSB_U3_PORT_SSP_SPEED);
@@ -831,6 +832,7 @@  static void mtu3_check_params(struct mtu3 *mtu)
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		break;
 	default:
 		dev_err(mtu->dev, "invalid max_speed: %s\n",
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index ad0eeac4332d..1545d139907c 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -74,6 +74,7 @@  static int mtu3_ep_enable(struct mtu3_ep *mep)
 	switch (mtu->g.speed) {
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		if (usb_endpoint_xfer_int(desc) ||
 				usb_endpoint_xfer_isoc(desc)) {
 			interval = desc->bInterval;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index a21074861f91..af8674d95820 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -657,7 +657,7 @@  struct usb_device {
 	enum usb_device_speed	speed;
 	unsigned int		rx_lanes;
 	unsigned int		tx_lanes;
-	enum usb_ssp_rate	ssp_rate;
+	enum usb_ssp_gen	ssp_gen;
 
 	struct usb_tt	*tt;
 	int		ttport;
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index c93b410b314a..bf9d66399d46 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -32,21 +32,15 @@ 
 
 #include <uapi/linux/usb/ch9.h>
 
-/* USB 3.2 SuperSpeed Plus phy signaling rate generation and lane count */
-
-enum usb_ssp_rate {
-	USB_SSP_GEN_UNKNOWN = 0,
-	USB_SSP_GEN_2x1,
-	USB_SSP_GEN_1x2,
-	USB_SSP_GEN_2x2,
-};
-
 struct device;
 
 extern const char *usb_ep_type_string(int ep_type);
 extern const char *usb_speed_string(enum usb_device_speed speed);
+extern const char *usb_speed_value(enum usb_device_speed speed);
+extern const char *usb_ssp_gen_name(enum usb_ssp_gen gen);
+extern enum usb_device_speed usb_speed_from_name(const char *speed_name);
 extern enum usb_device_speed usb_get_maximum_speed(struct device *dev);
-extern enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev);
+extern enum usb_ssp_gen usb_get_maximum_ssp_gen(struct device *dev);
 extern const char *usb_state_string(enum usb_device_state state);
 unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd,
 				 enum usb_device_speed speed);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 75bda0783395..6f8040e3e29b 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -324,8 +324,8 @@  struct usb_gadget_ops {
 			struct usb_gadget_driver *);
 	int	(*udc_stop)(struct usb_gadget *);
 	void	(*udc_set_speed)(struct usb_gadget *, enum usb_device_speed);
-	void	(*udc_set_ssp_rate)(struct usb_gadget *gadget,
-			enum usb_ssp_rate rate);
+	void	(*udc_set_ssp_gen)(struct usb_gadget *gadget,
+			enum usb_ssp_gen gen);
 	void	(*udc_async_callbacks)(struct usb_gadget *gadget, bool enable);
 	struct usb_ep *(*match_ep)(struct usb_gadget *,
 			struct usb_endpoint_descriptor *,
@@ -420,8 +420,8 @@  struct usb_gadget {
 	enum usb_device_speed		max_speed;
 
 	/* USB SuperSpeed Plus only */
-	enum usb_ssp_rate		ssp_rate;
-	enum usb_ssp_rate		max_ssp_rate;
+	enum usb_ssp_gen		ssp_gen;
+	enum usb_ssp_gen		max_ssp_gen;
 
 	enum usb_device_state		state;
 	const char			*name;
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index 8a147abfc680..3522e2c20599 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -1181,10 +1181,19 @@  enum usb_device_speed {
 	USB_SPEED_LOW, USB_SPEED_FULL,		/* usb 1.1 */
 	USB_SPEED_HIGH,				/* usb 2.0 */
 	USB_SPEED_WIRELESS,			/* wireless (usb 2.5) */
-	USB_SPEED_SUPER,			/* usb 3.0 */
-	USB_SPEED_SUPER_PLUS,			/* usb 3.1 */
+	USB_SPEED_SUPER,			/* usb 3.0 5Gbps */
+	USB_SPEED_SUPER_PLUS,			/* usb 3.1 10Gbps */
+	USB_SPEED_SUPER_PLUS_BY2,		/* usb 3.2 20Gbps */
 };
 
+/* USB 3.2 SuperSpeed Plus phy signaling generation and lane count */
+
+enum usb_ssp_gen {
+	USB_SSP_GEN_UNKNOWN = 0,
+	USB_SSP_GEN_2x1,
+	USB_SSP_GEN_1x2,
+	USB_SSP_GEN_2x2,
+};
 
 enum usb_device_state {
 	/* NOTATTACHED isn't in the USB spec, and this state acts
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1b2edc0fd2e9..13c7da24571b 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -571,19 +571,15 @@  static void usb_audio_make_longname(struct usb_device *dev,
 
 	switch (snd_usb_get_speed(dev)) {
 	case USB_SPEED_LOW:
-		strlcat(card->longname, ", low speed", sizeof(card->longname));
-		break;
 	case USB_SPEED_FULL:
-		strlcat(card->longname, ", full speed", sizeof(card->longname));
-		break;
 	case USB_SPEED_HIGH:
-		strlcat(card->longname, ", high speed", sizeof(card->longname));
-		break;
 	case USB_SPEED_SUPER:
-		strlcat(card->longname, ", super speed", sizeof(card->longname));
-		break;
 	case USB_SPEED_SUPER_PLUS:
-		strlcat(card->longname, ", super speed plus", sizeof(card->longname));
+	case USB_SPEED_SUPER_PLUS_BY2:
+		strlcat(card->longname, ", ", sizeof(card->longname));
+		strlcat(card->longname,
+			usb_speed_string(snd_usb_get_speed(dev)),
+			sizeof(card->longname));
 		break;
 	default:
 		break;
@@ -612,6 +608,7 @@  static int snd_usb_audio_create(struct usb_interface *intf,
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		break;
 	default:
 		dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev));
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index bf80e55d013a..0cac8e0177e4 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -110,6 +110,7 @@  unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		if (get_endpoint(alts, 0)->bInterval >= 1 &&
 		    get_endpoint(alts, 0)->bInterval <= 4)
 			return get_endpoint(alts, 0)->bInterval - 1;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 6b0993258e03..47159aaba8d5 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -897,6 +897,7 @@  static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
+	case USB_SPEED_SUPER_PLUS_BY2:
 		count = 1;
 		break;
 	default:
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index cbaa1b9fdeac..6f6675c92e0c 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -98,8 +98,9 @@  enum usb_device_speed {
 	USB_SPEED_LOW, USB_SPEED_FULL,		/* usb 1.1 */
 	USB_SPEED_HIGH,				/* usb 2.0 */
 	USB_SPEED_WIRELESS,			/* wireless (usb 2.5) */
-	USB_SPEED_SUPER,			/* usb 3.0 */
-	USB_SPEED_SUPER_PLUS,			/* usb 3.1 */
+	USB_SPEED_SUPER,			/* usb 3.0 5Gbps */
+	USB_SPEED_SUPER_PLUS,			/* usb 3.1 10Gbps */
+	USB_SPEED_SUPER_PLUS_BY2,		/* usb 3.2 20Gbps */
 };
 
 /*-------------------------------------------------------------------------*/
@@ -114,6 +115,7 @@  static char *speed (enum usb_device_speed s)
 	case USB_SPEED_WIRELESS:	return "wireless";
 	case USB_SPEED_SUPER:		return "super";
 	case USB_SPEED_SUPER_PLUS:	return "super-plus";
+	case USB_SPEED_SUPER_PLUS_BY2:	return "super-plus-by2";
 	default:			return "??";
 	}
 }