• Colin Cross's avatar
    PM: Prevent waiting forever on asynchronous resume after failing suspend · 152e1d59
    Colin Cross authored
    During suspend, the power.completion is expected to be set when a
    device has not yet started suspending.  Set it on init to fix a
    corner case where a device is resumed when its parent has never
    suspended.
    
    Consider three drivers, A, B, and C.  The parent of A is C, and C
    has async_suspend set.  On boot, C->power.completion is initialized
    to 0.
    
    During the first suspend:
    suspend_devices_and_enter(...)
     dpm_resume(...)
      device_suspend(A)
      device_suspend(B) returns error, aborts suspend
     dpm_resume_end(...)
       dpm_resume(...)
        device_resume(A)
         dpm_wait(A->parent == C)
          wait_for_completion(C->power.completion)
    
    The wait_for_completion will never complete, because
    complete_all(C->power.completion) will only be called from
    device_suspend(C) or device_resume(C), neither of which is called
    if suspend is aborted before C.
    
    After a successful suspend->resume cycle, where B doesn't abort
    suspend, C->power.completion is left in the completed state by the
    call to device_resume(C), and the same call path will work if B
    aborts suspend.
    Signed-off-by: default avatarColin Cross <ccross@android.com>
    Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
    152e1d59
main.c 26.4 KB