linux/kernel/time
Rafael J. Wysocki 124cf9117c PM / sleep: Make it possible to quiesce timers during suspend-to-idle
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: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
2015-02-15 19:40:09 +01:00
..
alarmtimer.c all arches, signal: move restart_block to struct task_struct 2015-02-12 18:54:12 -08:00
clockevents.c clockevents: Prevent shift out of bounds 2014-10-25 10:43:15 +02:00
clocksource.c time: move the timecounter/cyclecounter code into its own file. 2014-12-30 18:29:25 -05:00
hrtimer.c all arches, signal: move restart_block to struct task_struct 2015-02-12 18:54:12 -08:00
itimer.c time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
jiffies.c time: Fix overflow when HZ is smaller than 60 2014-02-06 16:01:40 +01:00
Kconfig clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
Makefile time: move the timecounter/cyclecounter code into its own file. 2014-12-30 18:29:25 -05:00
ntp_internal.h timekeeping: Convert timekeeping core to use timespec64s 2014-07-23 10:17:54 -07:00
ntp.c Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-02-09 16:33:07 -08:00
posix-clock.c
posix-cpu-timers.c all arches, signal: move restart_block to struct task_struct 2015-02-12 18:54:12 -08:00
posix-timers.c posix-timers: Fix stack info leak in timer_create() 2014-10-25 10:43:15 +02:00
sched_clock.c sched_clock: Avoid corrupting hrtimer tree during suspend 2014-07-24 12:02:49 +02:00
test_udelay.c time: Rename udelay_test.c to test_udelay.c 2014-11-21 11:59:55 -08:00
tick-broadcast-hrtimer.c tick: Fixup more fallout from hrtimer broadcast mode 2014-02-09 15:11:47 +01:00
tick-broadcast.c time: Replace __get_cpu_var uses 2014-08-26 13:45:44 -04:00
tick-common.c PM / sleep: Make it possible to quiesce timers during suspend-to-idle 2015-02-15 19:40:09 +01:00
tick-internal.h nohz: Move nohz full init call to tick init 2014-09-13 18:34:44 +02:00
tick-oneshot.c time: Replace __get_cpu_var uses 2014-08-26 13:45:44 -04:00
tick-sched.c Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-12-19 13:29:20 -08:00
time.c Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-01-25 17:47:34 -08:00
timeconst.bc time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
timeconv.c
timecounter.c timecounter: keep track of accumulated fractional nanoseconds 2014-12-30 18:29:27 -05:00
timekeeping_debug.c timekeeping: Convert timekeeping core to use timespec64s 2014-07-23 10:17:54 -07:00
timekeeping_internal.h clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
timekeeping.c PM / sleep: Make it possible to quiesce timers during suspend-to-idle 2015-02-15 19:40:09 +01:00
timekeeping.h PM / sleep: Make it possible to quiesce timers during suspend-to-idle 2015-02-15 19:40:09 +01:00
timer_list.c timer_list: correct the iterator for timer_list 2013-08-28 19:26:38 -07:00
timer_stats.c timer stats: Add a 'Collection: active/inactive' line to timer usage statistics 2013-10-10 09:59:25 +02:00
timer.c rcu: Remove "cpu" argument to rcu_check_callbacks() 2014-11-03 19:20:11 -08:00