diff options
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 49 |
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); | |||
32 | static int enabled_devices; | 33 | static int enabled_devices; |
33 | static int off __read_mostly; | 34 | static int off __read_mostly; |
34 | static int initialized __read_mostly; | 35 | static int initialized __read_mostly; |
35 | static bool use_deepest_state __read_mostly; | ||
36 | 36 | ||
37 | int cpuidle_disabled(void) | 37 | int 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 | */ | ||
78 | void 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 | */ |
88 | static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | 73 | static 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 | */ | ||
97 | void 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 | */ |
201 | void cpuidle_reflect(struct cpuidle_device *dev, int index) | 204 | void 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 | ||