• Rafael J. Wysocki's avatar
    PM / sleep: Make it possible to quiesce timers during suspend-to-idle · 124cf911
    Rafael J. Wysocki authored
    
    
    The efficiency of suspend-to-idle depends on being able to keep CPUs
    in the deepest available idle states for as much time as possible.
    Ideally, they should only be brought out of idle by system wakeup
    interrupts.
    
    However, timer interrupts occurring periodically prevent that from
    happening and it is not practical to chase all of the "misbehaving"
    timers in a whack-a-mole fashion.  A much more effective approach is
    to suspend the local ticks for all CPUs and the entire timekeeping
    along the lines of what is done during full suspend, which also
    helps to keep suspend-to-idle and full suspend reasonably similar.
    
    The idea is to suspend the local tick on each CPU executing
    cpuidle_enter_freeze() and to make the last of them suspend the
    entire timekeeping.  That should prevent timer interrupts from
    triggering until an IO interrupt wakes up one of the CPUs.  It
    needs to be done with interrupts disabled on all of the CPUs,
    though, because otherwise the suspended clocksource might be
    accessed by an interrupt handler which might lead to fatal
    consequences.
    
    Unfortunately, the existing ->enter callbacks provided by cpuidle
    drivers generally cannot be used for implementing that, because some
    of them re-enable interrupts temporarily and some idle entry methods
    cause interrupts to be re-enabled automatically on exit.  Also some
    of these callbacks manipulate local clock event devices of the CPUs
    which really shouldn't be done after suspending their ticks.
    
    To overcome that difficulty, introduce a new cpuidle state callback,
    ->enter_freeze, that will be guaranteed (1) to keep interrupts
    disabled all the time (and return with interrupts disabled) and (2)
    not to touch the CPU timer devices.  Modify cpuidle_enter_freeze() to
    look for the deepest available idle state with ->enter_freeze present
    and to make the CPU execute that callback with suspended tick (and the
    last of the online CPUs to execute it with suspended timekeeping).
    
    Suggested-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    124cf911