gregkh / usbutils

USB utilities for Linux, including lsusb
http://www.linux-usb.org
356 stars 202 forks source link

lsusb-t.c: fix tree mode for dual-lane modes of USB 3.2 #117

Closed KLZ-0 closed 3 years ago

KLZ-0 commented 3 years ago

For dual-lane modes of USB 3.2 Gen1x2 and Gen2x2 (and also asymmetric SSIC links). This would be useful to determine the real speed of multi-lane devices.

rzsn commented 3 years ago

It is single cable. The TypeC standard is basically an USB2 (DM/DN pair) plus 4 high speed lanes - which can be assigned to one or more protocols (e.g. a 2 lane DP + USB3.0), or two parallel connections of USB3 - either at 5Gb/s or 10Gb/s, leading to a total BW of 10Gb/s and 20Gb/s. The approach is more like a PCIe - where you increase the number of parallel connections to get a faster interface.

I did a test with various ASMedia chips (both a PCIe host controller and as a USB to NVMe bridge), with some of them having kernel/driver bugs, as the current status told to kernel is not indicating a higher mode (either speed or lane count), yet the hdparm -t measurement indicates a performance that tells its linked on something higher. I think these bugs are out of scope of usb-utils.

For me these patches bring clarity in what mode the device is operating.

rzsn commented 3 years ago

But not always. Sometimes it is so called Multi-Port Configuration with 2 or 3 cables (see page 30 of https://usbpd.files.wordpress.com/2019/02/16-usb_devdays_taipei_2017_active_cable.pdf). How are you planning to support those, or it does not matter, as it is abstractly the same?

That is only a mechanical/thermal consideration for spacing. Not an actual ganging of multiple physical into one logical connections to make a faster one.

More like Thunderbolt 3 in PCIe ;)

Please keep on the subject. There is no TB3 in PCIe, while I am familiar with this as well, will not further go into this.

I.e. more like 20 gbit/s? I.e. you are having Samsung NVMe 960 Pro in NVMe to USB-C 3.2 2x2? Or maybe USB4?

No. The problem with the kernel drivers/asmedia chipsets (using Gentoo, with 5.9.3) is the indication of the negotiated mode on the connected device. When a 1x10G device is connected (ASM2362), I get in both cases about 900MB/s, yet in lsusb I see this:

WRONG on ASM3242 add-in card by Orico:

lsusb -t
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M/x2
    |__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=uas, 5000M

GOOD on the onboard ASM2142 on Asus mainboard:

lsusb -t
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
    |__ Port 2: Dev 3, If 0, Class=Mass Storage, Driver=uas, 10000M

I used also a better - ASM2364 enclosure as well (2x10G), and I have seen 5000M/x2, yet the hdparm pulled 1900 MB/s.

Adding debug information to the USB driver I traced it back to a likely bug in ASMedia firmware on that new 2x10G add-in card:

WRONG on ASM3242 add-in card by Orico:

[  116.638334] usb usb4: hub_ext_port_status(port1:1) = 0
[  116.638340] usb usb4: hub_is_superspeedplus! ext_portstatus=00000044
[  116.638344] usb usb4: hub_is_superspeed!
[  116.638347] usb usb4: port_speed_is_ssp
[  116.638350] usb usb4: ... ssa_count = 4
[  116.638354] usb usb4: ... ss_attr[0] = 00050034
[  116.638357] usb usb4: ... return !!(USB_SSP_SUBLINK_SPEED_LP=0)
[  116.693546] usb 4-1: new SuperSpeed Gen 1 USB device number 2 using xhci_hcd
[  116.708498] usb 4-1: New USB device found, idVendor=174c, idProduct=2362, bcdDevice= 1.00
[  116.708506] usb 4-1: New USB device strings: Mfr=2, Product=3, SerialNumber=1

GOOD on onboard ASM2142 on Asus mainboard:

[   75.198341] usb usb6: hub_ext_port_status(port1:2) = 0
[   75.198347] usb usb6: hub_is_superspeedplus! ext_portstatus=00000055
[   75.198351] usb usb6: hub_is_superspeed!
[   75.198353] usb usb6: port_speed_is_ssp
[   75.198356] usb usb6: ... ssa_count = 4
[   75.198359] usb usb6: ... ss_attr[0] = 00050034
[   75.198362] usb usb6: ... ss_attr[1] = 000500b4
[   75.198365] usb usb6: ... ss_attr[2] = 000a4035
[   75.198369] usb usb6: ... return !!(USB_SSP_SUBLINK_SPEED_LP=16384)
[   75.253461] usb 6-2: new SuperSpeedPlus Gen 2 USB device number 2 using xhci_hcd
[   75.276758] usb 6-2: New USB device found, idVendor=174c, idProduct=2362, bcdDevice= 1.00
[   75.276766] usb 6-2: New USB device strings: Mfr=2, Product=3, SerialNumber=1

The ext_portstatus is the result of the hub_ext_port_status() call, which just wraps the get_port_status() function, that sends an USB_REQ_GET_STATUS request.

It seems that the controller itself forms a bad result of 0x0044, instead of the correct 0x0055 answer.

gregkh commented 3 years ago

If you could rework this into 1 patch that would be great, thanks!

rzsn commented 3 years ago

Can you provide an example output here in the changelog as to what this will look like?

And I need a "real" name for the signed-off-by line, thanks.

An example output is as:

$ lsusb -t
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
    |__ Port 2: Dev 2, If 0, Class=Mass Storage, Driver=uas, 10000M
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M/x2
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M/x2
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/10p, 5000M
    |__ Port 5: Dev 2, If 0, Class=Hub, Driver=hub/4p, 5000M
    |__ Port 6: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
    |__ Port 5: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
    |__ Port 14: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 14: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M

The first UAS device is a "10G usb-nvme enclosure" on a TypeA 10G port, the other one is a "20G usb-nvme enclosure" on a TypeC addon card, and uses 2x10G lanes - indicated by the /x2 suffix this patch creates. The mis-detection of the device having a 5G speed is due to some firmware bug I commented above - the kernel is told wrong about the negotiated speed by the hardware, but the device does run in fact at the 10Gx2 speed (max what the host is capable), based on a quick speed test (13.5Gb/s of payload):

$ sudo hdparm -t /dev/sdf

/dev/sdf:
 Timing buffered disk reads:  5080 MB in  3.00 seconds = 1693.05 MB/sec

I am Daniel Rozsnyo, initiator/tester of the patch. There is no need to separate commits, you can squash them, we just had multiple iterations to get to the final formatting.

I wanted to have a separator included (slash used here), in order to separate the lane count as 10000Mx2 would be confusing The other option considered was a 2x10000M format, but that does not play well with asymmetric link width (those are really uncommon, yet supported in the kernel). The expected output for asymmetric case, based on source code is:

... Driver=..., 5000M/Tx1+Rx3

Where the x symbol serves both as "times" count and also in Rx/Tx receive/transmit labelling. Either way you read it, it will be correct.

I have no access to USB4 system yet, but I assume its 40G mode will appear as 20Gx2 as well. And future slash-something output can serve to provide other very important detail, in a simple way.

KLZ-0 commented 3 years ago

It should be good now

gregkh commented 3 years ago

THanks, looks good!