diff options
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 13 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 7 | ||||
-rw-r--r-- | kernel/sched/idle.c | 13 |
3 files changed, 26 insertions, 7 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index c73207abb5a4..afc005b917fe 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -97,7 +97,17 @@ static int find_deepest_state(struct cpuidle_driver *drv, | |||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | #ifdef CONFIG_SUSPEND | 100 | /* Set the current cpu to use the deepest idle state, override governors */ |
101 | void cpuidle_use_deepest_state(bool enable) | ||
102 | { | ||
103 | struct cpuidle_device *dev; | ||
104 | |||
105 | preempt_disable(); | ||
106 | dev = cpuidle_get_device(); | ||
107 | dev->use_deepest_state = enable; | ||
108 | preempt_enable(); | ||
109 | } | ||
110 | |||
101 | /** | 111 | /** |
102 | * cpuidle_find_deepest_state - Find the deepest available idle state. | 112 | * cpuidle_find_deepest_state - Find the deepest available idle state. |
103 | * @drv: cpuidle driver for the given CPU. | 113 | * @drv: cpuidle driver for the given CPU. |
@@ -109,6 +119,7 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | |||
109 | return find_deepest_state(drv, dev, UINT_MAX, 0, false); | 119 | return find_deepest_state(drv, dev, UINT_MAX, 0, false); |
110 | } | 120 | } |
111 | 121 | ||
122 | #ifdef CONFIG_SUSPEND | ||
112 | static void enter_freeze_proper(struct cpuidle_driver *drv, | 123 | static void enter_freeze_proper(struct cpuidle_driver *drv, |
113 | struct cpuidle_device *dev, int index) | 124 | struct cpuidle_device *dev, int index) |
114 | { | 125 | { |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 15deea449edc..da346f2817a8 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -74,6 +74,7 @@ struct cpuidle_driver_kobj; | |||
74 | struct cpuidle_device { | 74 | struct cpuidle_device { |
75 | unsigned int registered:1; | 75 | unsigned int registered:1; |
76 | unsigned int enabled:1; | 76 | unsigned int enabled:1; |
77 | unsigned int use_deepest_state:1; | ||
77 | unsigned int cpu; | 78 | unsigned int cpu; |
78 | 79 | ||
79 | int last_residency; | 80 | int last_residency; |
@@ -192,11 +193,12 @@ static inline struct cpuidle_driver *cpuidle_get_cpu_driver( | |||
192 | static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; } | 193 | static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; } |
193 | #endif | 194 | #endif |
194 | 195 | ||
195 | #if defined(CONFIG_CPU_IDLE) && defined(CONFIG_SUSPEND) | 196 | #ifdef CONFIG_CPU_IDLE |
196 | extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | 197 | extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv, |
197 | struct cpuidle_device *dev); | 198 | struct cpuidle_device *dev); |
198 | extern int cpuidle_enter_freeze(struct cpuidle_driver *drv, | 199 | extern int cpuidle_enter_freeze(struct cpuidle_driver *drv, |
199 | struct cpuidle_device *dev); | 200 | struct cpuidle_device *dev); |
201 | extern void cpuidle_use_deepest_state(bool enable); | ||
200 | #else | 202 | #else |
201 | static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | 203 | static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv, |
202 | struct cpuidle_device *dev) | 204 | struct cpuidle_device *dev) |
@@ -204,6 +206,9 @@ static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | |||
204 | static inline int cpuidle_enter_freeze(struct cpuidle_driver *drv, | 206 | static inline int cpuidle_enter_freeze(struct cpuidle_driver *drv, |
205 | struct cpuidle_device *dev) | 207 | struct cpuidle_device *dev) |
206 | {return -ENODEV; } | 208 | {return -ENODEV; } |
209 | static inline void cpuidle_use_deepest_state(bool enable) | ||
210 | { | ||
211 | } | ||
207 | #endif | 212 | #endif |
208 | 213 | ||
209 | /* kernel/sched/idle.c */ | 214 | /* kernel/sched/idle.c */ |
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 1d8718d5300d..513e4dfeeae7 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c | |||
@@ -164,11 +164,14 @@ static void cpuidle_idle_call(void) | |||
164 | * timekeeping to prevent timer interrupts from kicking us out of idle | 164 | * timekeeping to prevent timer interrupts from kicking us out of idle |
165 | * until a proper wakeup interrupt happens. | 165 | * until a proper wakeup interrupt happens. |
166 | */ | 166 | */ |
167 | if (idle_should_freeze()) { | 167 | |
168 | entered_state = cpuidle_enter_freeze(drv, dev); | 168 | if (idle_should_freeze() || dev->use_deepest_state) { |
169 | if (entered_state > 0) { | 169 | if (idle_should_freeze()) { |
170 | local_irq_enable(); | 170 | entered_state = cpuidle_enter_freeze(drv, dev); |
171 | goto exit_idle; | 171 | if (entered_state > 0) { |
172 | local_irq_enable(); | ||
173 | goto exit_idle; | ||
174 | } | ||
172 | } | 175 | } |
173 | 176 | ||
174 | next_state = cpuidle_find_deepest_state(drv, dev); | 177 | next_state = cpuidle_find_deepest_state(drv, dev); |