Re: [RFC PATCH] usb: core: defer leaf-device resume off the S3 critical path

Oliver Neukum <[email protected]> Wed, 5 Aug 2026 15:28:58 +0200
Newsgroups org.kernel.vger.linux-usb,org.kernel.vger.linux-kernel
Message-ID <[email protected]>

On 05.08.26 11:36, Hongyu Xie wrote:
> Problem:
> System resume (dpm_resume) invokes each device's resume callback
> synchronously on the wake-up critical path.  For a USB leaf device
> this means port resume and, when reset_resume is needed, a port
> reset that, for persistent devices, waits up to 2000 ms for the
> device connection (CCS; on SuperSpeed this includes link training)
> to be re-established (wait_for_connected()).  Slow link training of
> some U-disks and webcams after S3 power-on therefore stalls the
> entire system wake-up: on an
> arm64 test machine with four leaf devices (bluetooth, UVC camera,
> two U-disks) dpm_resume took 2508 ms, about 2.1 s of it caused by a
> single SanDisk U-disk whose link training stayed in Rx.Detect for
> 2000 ms (worst case: -ENODEV fallback to disconnect +
> re-enumeration).  A device compatibility issue should not lengthen
> the system-wide wake-up.
> 
> Fix:
> The patch addresses this on four levels:
> 
> 1. Defer leaf-device recovery off the critical path.  Leaf devices
>     (udev->parent && !udev->maxchild) that are port-suspended on
>     system resume have their real port resume moved to a per-device
>     work item queued from usb_resume_complete(), after all hubs have
>     finished resume.  The work reuses the same udev (in-place reset,
>     devnum preserved); drivers without reset_resume get unbind+rebind.

If you do this, you may have drivers which do not runtime PM
face devices that are effectively runtime suspended. This will
not work.
  
> 2. Safe abandonment.  If a new suspend or a disconnect arrives before
>     the work item runs, the reset is abandoned, not flushed: the
>     device is still port-suspended, which is exactly what the new
>     suspend needs, and the work item then only releases the runtime
>     reference it took.  The abandon decision is serialized with the
>     work item by the device lock, so no cancel_work_sync() (which
>     would deadlock against the work item's device_lock()) is needed
>     on the suspend path.

You cannot do this without checking whether remote_wakeup is correctly
set.

Furthermore you cannot just use the system work queue for this.
You must not have any memory allocations with GFP_KERNEL on that
queue.

	Regards
		Oliver