After updating my Ubuntu 20.04 LTS installation’s Linux Kernel to 5.8 from 5.4, I started experiencing irregular problems with unresponsive USB devices after resuming from sleep. Once in every few wakeups, the USB mouse and Bluetooth transciever would ‘freeze’ and the devices vanish from the lsusb list. After some playing around, I found that unbinding and rebinding the XHCI driver resolved the issue for me.

When all works fine, the output of the lsusb command would look something like this:

→ lsusb -t    
/:  Bus 08.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 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/4p, 10000M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 480M
    |__ Port 1: Dev 2, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 1: Dev 2, If 1, Class=Wireless, Driver=btusb, 12M
    |__ Port 5: Dev 3, If 2, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 5: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 5: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 6: Dev 4, If 0, Class=Vendor Specific Class, Driver=, 12M
    |__ Port 6: Dev 4, If 2, Class=Human Interface Device, Driver=usbhid, 12M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 480M
    |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 2: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 2: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M

When the issue occurs, all entries under Bus 03.Port 1: Dev 1 would vanish. Rebooting the system would make the devices available again but this is hardly a solution. Luckily, another remedy that does not require restarting the system worked out: rebinding the driver.

Note the driver of the problematic root_hub: xhci_hcd, and the bus number: 03.

First, find out the PCI device identifier of the bus. In /sys/bus/usb/drivers/usb you will find links usbN where N is the bus number. Read the destination of the bus to find out the PCI device id. E.g., for bus 3:

→ lsusb readlink /sys/bus/usb/drivers/usb/usb3
../../../../devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:06:00.3/usb3

Note the last identifier in the format nnnn:nn:nn.n: 0000:06:00.3.

Now, rebind the driver: You will notice that the xhci_hcd driver directory in the device tree contains a link to the previously discovered PCI device and files bind and unbind.

→ ls /sys/bus/pci/drivers/xhci_hcd
0000:06:00.1
0000:06:00.3
... etc ...
bind
unbind

To unbind and bind, write the PCI device ID into the unbind and bind files. You have to have permission to do that, so typically you would use sudo:

echo 0000:06:00.3 | sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind
echo 0000:06:00.3 | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind

Put this is a script somewhere in your path (e.g., ~/.local/bin/rebind-usb when ~/.local/bin is in your PATH). Next time that your devices are unresponsive: run rebind-usb and you should be good to go.