cpuidle / sleep: Use broadcast timer for states that stop local timer
[deliverable/linux.git] / drivers / cpuidle / cpuidle.c
index 8b3e132b6a01390d56c9c02bfbcbcdacfb99e057..080bd2dbde4ba5408504a451e9454b51497202e3 100644 (file)
@@ -44,8 +44,8 @@ void disable_cpuidle(void)
        off = 1;
 }
 
-static bool cpuidle_not_available(struct cpuidle_driver *drv,
-                                 struct cpuidle_device *dev)
+bool cpuidle_not_available(struct cpuidle_driver *drv,
+                          struct cpuidle_device *dev)
 {
        return off || !initialized || !drv || !dev || !dev->enabled;
 }
@@ -72,14 +72,8 @@ int cpuidle_play_dead(void)
        return -ENODEV;
 }
 
-/**
- * cpuidle_find_deepest_state - Find deepest state meeting specific conditions.
- * @drv: cpuidle driver for the given CPU.
- * @dev: cpuidle device for the given CPU.
- * @freeze: Whether or not the state should be suitable for suspend-to-idle.
- */
-static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
-                                     struct cpuidle_device *dev, bool freeze)
+static int find_deepest_state(struct cpuidle_driver *drv,
+                             struct cpuidle_device *dev, bool freeze)
 {
        unsigned int latency_req = 0;
        int i, ret = freeze ? -1 : CPUIDLE_DRIVER_STATE_START - 1;
@@ -98,6 +92,17 @@ static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
        return ret;
 }
 
+/**
+ * cpuidle_find_deepest_state - Find the deepest available idle state.
+ * @drv: cpuidle driver for the given CPU.
+ * @dev: cpuidle device for the given CPU.
+ */
+int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
+                              struct cpuidle_device *dev)
+{
+       return find_deepest_state(drv, dev, false);
+}
+
 static void enter_freeze_proper(struct cpuidle_driver *drv,
                                struct cpuidle_device *dev, int index)
 {
@@ -119,46 +124,26 @@ static void enter_freeze_proper(struct cpuidle_driver *drv,
 
 /**
  * cpuidle_enter_freeze - Enter an idle state suitable for suspend-to-idle.
+ * @drv: cpuidle driver for the given CPU.
+ * @dev: cpuidle device for the given CPU.
  *
  * If there are states with the ->enter_freeze callback, find the deepest of
- * them and enter it with frozen tick.  Otherwise, find the deepest state
- * available and enter it normally.
- *
- * Returns with enabled interrupts.
+ * them and enter it with frozen tick.
  */
-void cpuidle_enter_freeze(void)
+int cpuidle_enter_freeze(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
-       struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
-       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int index;
 
-       if (cpuidle_not_available(drv, dev))
-               goto fallback;
-
        /*
         * Find the deepest state with ->enter_freeze present, which guarantees
         * that interrupts won't be enabled when it exits and allows the tick to
         * be frozen safely.
         */
-       index = cpuidle_find_deepest_state(drv, dev, true);
-       if (index >= 0) {
+       index = find_deepest_state(drv, dev, true);
+       if (index >= 0)
                enter_freeze_proper(drv, dev, index);
-               local_irq_enable();
-               return;
-       }
 
-       /*
-        * It is not safe to freeze the tick, find the deepest state available
-        * at all and try to enter it normally.
-        */
-       index = cpuidle_find_deepest_state(drv, dev, false);
-       if (index >= 0) {
-               cpuidle_enter(drv, dev, index);
-               return;
-       }
-
- fallback:
-       arch_cpu_idle();
+       return index;
 }
 
 /**
@@ -217,9 +202,6 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
  */
 int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
-       if (cpuidle_not_available(drv, dev))
-               return -ENODEV;
-
        return cpuidle_curr_governor->select(drv, dev);
 }
 
This page took 0.044916 seconds and 5 git commands to generate.