PM / sleep: Make it possible to quiesce timers during suspend-to-idle
[deliverable/linux.git] / kernel / time / tick-common.c
index 7efeedf53ebd1aa45f3286ad50da3e24c46f391a..f7c515595b42b2bf9794a8f3f4ee1f9a2c17df89 100644 (file)
@@ -394,6 +394,56 @@ void tick_resume(void)
        }
 }
 
+static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
+static unsigned int tick_freeze_depth;
+
+/**
+ * tick_freeze - Suspend the local tick and (possibly) timekeeping.
+ *
+ * Check if this is the last online CPU executing the function and if so,
+ * suspend timekeeping.  Otherwise suspend the local tick.
+ *
+ * Call with interrupts disabled.  Must be balanced with %tick_unfreeze().
+ * Interrupts must not be enabled before the subsequent %tick_unfreeze().
+ */
+void tick_freeze(void)
+{
+       raw_spin_lock(&tick_freeze_lock);
+
+       tick_freeze_depth++;
+       if (tick_freeze_depth == num_online_cpus()) {
+               timekeeping_suspend();
+       } else {
+               tick_suspend();
+               tick_suspend_broadcast();
+       }
+
+       raw_spin_unlock(&tick_freeze_lock);
+}
+
+/**
+ * tick_unfreeze - Resume the local tick and (possibly) timekeeping.
+ *
+ * Check if this is the first CPU executing the function and if so, resume
+ * timekeeping.  Otherwise resume the local tick.
+ *
+ * Call with interrupts disabled.  Must be balanced with %tick_freeze().
+ * Interrupts must not be enabled after the preceding %tick_freeze().
+ */
+void tick_unfreeze(void)
+{
+       raw_spin_lock(&tick_freeze_lock);
+
+       if (tick_freeze_depth == num_online_cpus())
+               timekeeping_resume();
+       else
+               tick_resume();
+
+       tick_freeze_depth--;
+
+       raw_spin_unlock(&tick_freeze_lock);
+}
+
 /**
  * tick_init - initialize the tick control
  */
This page took 0.029907 seconds and 5 git commands to generate.