• Jean-Francois Le Fillatre's avatar
    usb: add quirks for Lenovo OneLink+ Dock · 37d49519
    Jean-Francois Le Fillatre authored
    The Lenovo OneLink+ Dock contains two VL812 USB3.0 controllers:
    17ef:1018 upstream
    17ef:1019 downstream
    
    These hubs suffer from two separate problems:
    
    1) After the host system was suspended and woken up, the hubs appear to
       be in a random state. Some downstream ports (both internal to the
       built-in audio and network controllers, and external to USB sockets)
       may no longer be functional. The exact list of disabled ports (if
       any) changes from wakeup to wakeup. Ports remain in that state until
       the dock is power-cycled, or until the laptop is rebooted.
    
       Wakeup sources connected to the hubs (keyboard, WoL on the integrated
       gigabit controller) will wake the system up from suspend, but they
       may no longer work after wakeup (and in that case will no longer work
       as wakeup source in a subsequent suspend-wakeup cycle).
    
       This issue appears in the logs with messages such as:
    
         usb 1-6.1-port4: cannot disable (err = -71)
         usb 1-6-port2: cannot disable (err = -71)
         usb 1-6.1: clear tt 1 (80c0) error -71
         usb 1-6-port4: cannot disable (err = -71)
         usb 1-6.4: PM: dpm_run_callback(): usb_dev_resume+0x0/0x10 [usbcore] returns -71
         usb 1-6.4: PM: failed to resume async: error -71
         usb 1-7: reset full-speed USB device number 5 using xhci_hcd
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: Cannot enable. Maybe the USB cable is bad?
         usb 1-6.1-port1: cannot disable (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: cannot reset (err = -71)
         usb 1-6.1-port1: Cannot enable. Maybe the USB cable is bad?
         usb 1-6.1-port1: cannot disable (err = -71)
    
    2) Some USB devices cannot be enumerated properly. So far I have only
       seen the issue with USB 3.0 devices. The same devices work without
       problem directly connected to the host system, to other systems or to
       other hubs (even when those hubs are connected to the OneLink+ dock).
    
       One very reliable reproducer is this USB 3.0 HDD enclosure:
       152d:9561 JMicron Technology Corp. / JMicron USA Technology Corp. Mobius
    
       I have seen it happen sporadically with other USB 3.0 enclosures,
       with controllers from different manufacturers, all self-powered.
    
       Typical messages in the logs:
    
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         usb 2-1.4: device not accepting address 6, error -62
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         usb 2-1.4: device not accepting address 7, error -62
         usb 2-1-port4: attempt power cycle
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         usb 2-1.4: device not accepting address 8, error -62
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
         usb 2-1.4: device not accepting address 9, error -62
         usb 2-1-port4: unable to enumerate USB device
    
    Through trial and error, I found that the USB_QUIRK_RESET_RESUME solved
    the second issue. Further testing then uncovered the first issue. Test
    results are summarized in this table:
    
    =======================================================================================
    Settings                        USB2 hotplug    USB3 hotplug    State after waking up
    ---------------------------------------------------------------------------------------
    
    power/control=auto              works           fails           broken
    
    usbcore.autosuspend=-1          works           works           broken
    OR power/control=on
    
    power/control=auto              works (1)       works (1)       works
    and USB_QUIRK_RESET_RESUME
    
    power/control=on                works           works           works
    and USB_QUIRK_RESET_RESUME
    
    HUB_QUIRK_DISABLE_AUTOSUSPEND   works           works           works
    and USB_QUIRK_RESET_RESUME
    
    =======================================================================================
    
    In those results, the power/control settings are applied to both hubs,
    both on the USB2 and USB3 side, before each test.
    
    From those results, USB_QUIRK_RESET_RESUME is required to reset the hubs
    properly after a suspend-wakeup cycle, and the hubs must not autosuspend
    to work around the USB3 issue.
    
    A secondary effect of USB_QUIRK_RESET_RESUME is to prevent the hubs'
    upstream links from suspending (the downstream ports can still suspend).
    This secondary effect is used in results (1). It is enough to solve the
    USB3 problem.
    
    Setting USB_QUIRK_RESET_RESUME on those hubs is the smallest patch that
    solves both issues.
    
    Prior to creating this patch, I have used the USB_QUIRK_RESET_RESUME via
    the kernel command line for over a year without noticing any side
    effect.
    
    Thanks to Oliver Neukum @Suse for explanations of the operations of
    USB_QUIRK_RESET_RESUME, and requesting more testing.
    Signed-off-by: default avatarJean-Francois Le Fillatre <jflf_kernel@gmx.com>
    Cc: stable <stable@kernel.org>
    Link: https://lore.kernel.org/r/20220927073407.5672-1-jflf_kernel@gmx.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    37d49519
quirks.c 20.7 KB