aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/cpuidle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r--drivers/cpuidle/cpuidle.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 125150dc6e81..23a8d6cc8d30 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -19,6 +19,7 @@
19#include <linux/ktime.h> 19#include <linux/ktime.h>
20#include <linux/hrtimer.h> 20#include <linux/hrtimer.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/suspend.h>
22#include <trace/events/power.h> 23#include <trace/events/power.h>
23 24
24#include "cpuidle.h" 25#include "cpuidle.h"
@@ -32,7 +33,6 @@ LIST_HEAD(cpuidle_detected_devices);
32static int enabled_devices; 33static int enabled_devices;
33static int off __read_mostly; 34static int off __read_mostly;
34static int initialized __read_mostly; 35static int initialized __read_mostly;
35static bool use_deepest_state __read_mostly;
36 36
37int cpuidle_disabled(void) 37int cpuidle_disabled(void)
38{ 38{
@@ -66,24 +66,9 @@ int cpuidle_play_dead(void)
66} 66}
67 67
68/** 68/**
69 * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode. 69 * cpuidle_find_deepest_state - Find deepest state meeting specific conditions.
70 * @enable: Whether enable or disable the feature. 70 * @drv: cpuidle driver for the given CPU.
71 * 71 * @dev: cpuidle device for the given CPU.
72 * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and
73 * always use the state with the greatest exit latency (out of the states that
74 * are not disabled).
75 *
76 * This function can only be called after cpuidle_pause() to avoid races.
77 */
78void cpuidle_use_deepest_state(bool enable)
79{
80 use_deepest_state = enable;
81}
82
83/**
84 * cpuidle_find_deepest_state - Find the state of the greatest exit latency.
85 * @drv: cpuidle driver for a given CPU.
86 * @dev: cpuidle device for a given CPU.
87 */ 72 */
88static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, 73static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
89 struct cpuidle_device *dev) 74 struct cpuidle_device *dev)
@@ -105,6 +90,27 @@ static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
105} 90}
106 91
107/** 92/**
93 * cpuidle_enter_freeze - Enter an idle state suitable for suspend-to-idle.
94 *
95 * Find the deepest state available and enter it.
96 */
97void cpuidle_enter_freeze(void)
98{
99 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
100 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
101 int index;
102
103 index = cpuidle_find_deepest_state(drv, dev);
104 if (index >= 0)
105 cpuidle_enter(drv, dev, index);
106 else
107 arch_cpu_idle();
108
109 /* Interrupts are enabled again here. */
110 local_irq_disable();
111}
112
113/**
108 * cpuidle_enter_state - enter the state and update stats 114 * cpuidle_enter_state - enter the state and update stats
109 * @dev: cpuidle device for this cpu 115 * @dev: cpuidle device for this cpu
110 * @drv: cpuidle driver for this cpu 116 * @drv: cpuidle driver for this cpu
@@ -166,9 +172,6 @@ int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
166 if (!drv || !dev || !dev->enabled) 172 if (!drv || !dev || !dev->enabled)
167 return -EBUSY; 173 return -EBUSY;
168 174
169 if (unlikely(use_deepest_state))
170 return cpuidle_find_deepest_state(drv, dev);
171
172 return cpuidle_curr_governor->select(drv, dev); 175 return cpuidle_curr_governor->select(drv, dev);
173} 176}
174 177
@@ -200,7 +203,7 @@ int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev,
200 */ 203 */
201void cpuidle_reflect(struct cpuidle_device *dev, int index) 204void cpuidle_reflect(struct cpuidle_device *dev, int index)
202{ 205{
203 if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state)) 206 if (cpuidle_curr_governor->reflect)
204 cpuidle_curr_governor->reflect(dev, index); 207 cpuidle_curr_governor->reflect(dev, index);
205} 208}
206 209