Bug 213839
Summary: | XHCI 7 port usb hub does not work correctly | ||
---|---|---|---|
Product: | Drivers | Reporter: | tomas m (tmezzadra) |
Component: | USB | Assignee: | Default virtual assignee for Drivers/USB (drivers_usb) |
Status: | NEW --- | ||
Severity: | normal | CC: | noodles, stulluk |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 5.13.4 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
Plugged in under Windows, USB flash drive inserted into port on second hub
Plugged in under Linux, USB flash drive inserted into port on second hub dmesg, no usb autosuspend, hub working dmesg, usb autosuspend, usb_snoop, hub not working dmesg, usb autosuspend, 2 drives, working Mark child resume requests in hub->event_bits, not hub->change_bits |
Description
tomas m
2021-07-24 13:41:17 UTC
This could easily be a power issue. Does either the 7-port hub or the device you plug into it have its own power source? (In reply to Alan Stern from comment #1) > This could easily be a power issue. Does either the 7-port hub or the > device you plug into it have its own power source? I measured the 5v on both chips and its 5v sharp. Soldered an additional cap to its vcc too. Its the same vcc source. Like i said. Under windows it works It is being powered by the usb port. I will test an external suppy just to be safe and report Have you tried using Wireshark to capture the USB communications to/from the hub under both Windows and Linux for comparison? If there's a difference, it should show up. I have exactly the same device, it is sold as USB3.0, but I observe same behaviour ( detected as USB2.0) on all my computers. Tomorrow I will find a chance to try it on a Windows machine, and report back. I've just ended up with one of these devices and see the same behaviour; on Linux (5.10.70 from Debian) only 3 ports are operational, whereas when plugged into a Windows laptop all 7 ports work. It seems this is a knock-off hub - it was sold as 480Mb/s capable, but is only reporting itself as full-speed (12Mb/s). As Tomas reports it shows up as 2 USB hubs - lsusb -vv output as follows: Bus 003 Device 080: ID 0a05:7211 Unknown Manufacturer hub Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 9 Hub bDeviceSubClass 0 bDeviceProtocol 0 Full speed (or root) hub bMaxPacketSize0 8 idVendor 0x0a05 Unknown Manufacturer idProduct 0x7211 hub bcdDevice 1.00 iManufacturer 0 iProduct 1 USB2.0 HUB iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x0019 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 9 Hub bInterfaceSubClass 0 bInterfaceProtocol 0 Full speed (or root) hub iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0001 1x 1 bytes bInterval 255 Apparently the chip involved is a Micov MW7211 which is a single chip full-speed hub solution. I've no particular interest in seeing this work, given that it's not high-speed capable, but figured the additional information might be helpful as there's obviously some difference in the way Windows is driving the hub compared to Linux. What would actually be useful would be USB packet traces for the hub recorded under both Linux and Windows, showing what happens when the hub is first plugged in and and then when another device is plugged into one of the non-working ports. This would allow us to compare the behavior of the two operating systems and look for differences. Created attachment 300189 [details]
Plugged in under Windows, USB flash drive inserted into port on second hub
Created attachment 300190 [details]
Plugged in under Linux, USB flash drive inserted into port on second hub
Attached files are hopefully helpful. Capture is started, hub is plugged in, USB3 flash drive is then plugged into a port off the second hub chip. In the Windows case it's detected fine (you can see the flurry of USB Mass Storage requests), in the Linux case there's some sort of disconnect/reconnect event but the flash drive never appears. So far I have only looked at the Linux trace. It shows two unusual things I don't understand. One is that some process (I don't know which) re-reads the hub's device and configuration descriptors while the second device is being initialized, and apparently as a result of this the process decides to reset the hub. Why does this happen? The second is that when the descriptors are re-read, the hub's config descriptor has changed! The original bmAttributes value is 0xe0, as shown in the lsusb output above. But the bmAttributes value in the trace is 0xc0; the changed bit is the flag for Wakeup support. Most likely this is a bug in the hub's firmware. Perhaps additional debugging information will help. You can enable dynamic debugging and snooping for USB by doing: echo 'module usbcore =p' >/sys/kernel/debug/dynamic_debug/control echo 1 >/sys/module/usbcore/parameters/usbfs_snoop Clear the kernel log buffer by doing: dmesg -C Then plug in the hub and and plug in a device to one of the non-working ports. Let's see what the dmesg log shows after that. Another unusual thing shows up clearly in the trace: The autosuspend_delay_ms time is set to a very low value; it looks like 20 ms. You might get better results leaving the delay set to its default value of 2 seconds. Or turn USB autosuspend off entirely by doing: echo -1 >/sys/module/usbcore/parameters/autosuspend before plugging in the hub. Autosuspend appears to be the issue; if I disable it using the echo command provided then the additional ports on the hub work ok and the flash drive is detected. Looking at my kernel config (this is Debian 11/bullseye, their stock 5.10.70-1 kernel) I see: CONFIG_USB_AUTOSUSPEND_DELAY=2 Which according to drivers/usb/core/Kconfig is the default. However hub_probe in drivers/usb/core/hub.c forces the suspend delay for a hub to 0ms as long as autosuspend is enabled. As an experiment, theorising if the first hub chip didn't get put immediately to sleep devices off the 2nd hub chip would be seen, I tried plugging in the hub, plugging a flash drive into a port on the first chip (which is seen, as expected) and then plugging a flash drive into a port on the second chip (which would normally not be seen). Both drives are correctly detected. I'll attach all 3 dmesgs now but it seems like the 0 delay in hub.c is what's causing the problem. Created attachment 300193 [details]
dmesg, no usb autosuspend, hub working
Created attachment 300194 [details]
dmesg, usb autosuspend, usb_snoop, hub not working
Created attachment 300195 [details]
dmesg, usb autosuspend, 2 drives, working
Created attachment 300199 [details]
Mark child resume requests in hub->event_bits, not hub->change_bits
Congratulations on tracking this down. Later on I will send you a patch to disable autosuspend for these hubs, if it turns out to be needed. But for now, I'd like to track down the exact pathway for the problem, if you don't mind.
Can you test the attached patch? It looks like there is a bug in the hub driver's resume handler. When a resuming hub sees that one of its downstream ports got a resume request from a child device, it sets a corresponding bit in the hub->change_bits variable. But this variable is meant for connection changes, not suspend/resume status changes; which explains why the child hub ends up getting reset. The bit should be set in the hub->event_bits variable instead. (If you read through port_event() and hub_event(), you'll see how the two variables are handled similarly but not exactly the same.)
This bug wasn't noticed before because non-buggy devices don't change their descriptors, and hub_port_connect_change() is careful to check for cases where there wasn't a real connection change (i.e., device is still connected, port is still enabled, and device descriptors haven't changed). But your buggy hub does change its config descriptor and so it gets reset.
Excellent. Your fix appears to make things work fine. Built it on top of 5.12.12, plugged in the hub, plugged flash drive into a port off the second hub chip and it gets detected fine: [ 64.055322] usb 1-1: new full-speed USB device number 2 using xhci_hcd [ 64.223348] usb 1-1: New USB device found, idVendor=0a05, idProduct=7211, bcdDevice= 1.00 [ 64.223357] usb 1-1: New USB device strings: Mfr=0, Product=1, SerialNumber=0 [ 64.223360] usb 1-1: Product: USB2.0 HUB [ 64.272644] hub 1-1:1.0: USB hub found [ 64.275305] hub 1-1:1.0: 4 ports detected [ 64.715299] usb 1-1.4: new full-speed USB device number 3 using xhci_hcd [ 64.843578] usb 1-1.4: New USB device found, idVendor=0a05, idProduct=7211, bcdDevice= 1.00 [ 64.843584] usb 1-1.4: New USB device strings: Mfr=0, Product=1, SerialNumber=0 [ 64.843586] usb 1-1.4: Product: USB2.0 HUB [ 64.880662] hub 1-1.4:1.0: USB hub found [ 64.883305] hub 1-1.4:1.0: 4 ports detected [ 78.843353] usb 1-1.4.2: new full-speed USB device number 4 using xhci_hcd [ 78.982539] usb 1-1.4.2: not running at top speed; connect to a high speed hub [ 79.000617] usb 1-1.4.2: New USB device found, idVendor=0951, idProduct=1697, bcdDevice= 1.00 [ 79.000626] usb 1-1.4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 79.000629] usb 1-1.4.2: Product: DT Ultimate G3 [ 79.000631] usb 1-1.4.2: Manufacturer: Kingston [ 79.000633] usb 1-1.4.2: SerialNumber: 0018F30C9F50BE5181712973 [ 79.013499] SCSI subsystem initialized [ 79.015328] usb-storage 1-1.4.2:1.0: USB Mass Storage device detected [ 79.015438] scsi host0: usb-storage 1-1.4.2:1.0 [ 79.015492] usbcore: registered new interface driver usb-storage [ 79.016658] usbcore: registered new interface driver uas [ 80.026221] scsi 0:0:0:0: Direct-Access Kingston DT Ultimate G3 PMAP PQ: 0 ANSI: 6 [ 80.029716] scsi 0:0:0:0: Attached scsi generic sg0 type 0 [ 80.032151] sd 0:0:0:0: [sda] 61407232 512-byte logical blocks: (31.4 GB/29.3 GiB) [ 80.033068] sd 0:0:0:0: [sda] Write Protect is off [ 80.033070] sd 0:0:0:0: [sda] Mode Sense: 2b 80 00 08 [ 80.033986] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA [ 80.271640] sda: sda1 [ 80.275055] sd 0:0:0:0: [sda] Attached SCSI removable disk [ 82.061123] EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: errors=remount-ro. Quota mode: none. (In reply to Jonathan McDowell from comment #16) > Excellent. Your fix appears to make things work fine. Built it on top of > 5.12.12, plugged in the hub, plugged flash drive into a port off the second > hub chip and it gets detected fine: Er, 5.15.12, i.e. latest stable, I didn't just pick a random kernel version to test! Good news! I have posted the patch on the linux-usb mailing list; it should get merged sometime in the next few weeks. |