aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 17:17:51 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 17:17:51 -0500
commit99fa0ad92c4fd8b529c89b3640b42323984be761 (patch)
treeba4ef84ab54c2c5636521c1b1ae4e9056d46c75c /drivers/cpuidle
parent1d9e71404e2c3f37387991534983dcb2ab05660d (diff)
parent5f5081852038d9a7b309190730bfb724b413235e (diff)
Merge tag 'suspend-to-idle-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull suspend-to-idle updates from Rafael Wysocki: "Suspend-to-idle timer quiescing support for v3.20-rc1 Until now suspend-to-idle has not been able to save much more energy than runtime PM because of timer interrupts that periodically bring CPUs out of idle while they are waiting for a wakeup interrupt. Of course, the timer interrupts are not wakeup ones, so the handling of them can be deferred until a real wakeup interrupt happens, but at the same time we don't want to mass-expire timers at that point. The solution is to suspend the entire timekeeping when the last CPU is entering an idle state and resume it when the first CPU goes out of idle. That has to be done with care, though, so as to avoid accessing suspended clocksources etc. end we need extra support from idle drivers for that. This series of commits adds support for quiescing timers during suspend-to-idle and adds the requisite callbacks to intel_idle and the ACPI cpuidle driver" * tag 'suspend-to-idle-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / idle: Implement ->enter_freeze callback routine intel_idle: Add ->enter_freeze callbacks PM / sleep: Make it possible to quiesce timers during suspend-to-idle timekeeping: Make it safe to use the fast timekeeper while suspended timekeeping: Pass readout base to update_fast_timekeeper() PM / sleep: Re-implement suspend-to-idle handling
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/cpuidle.c94
1 files changed, 68 insertions, 26 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 125150dc6e81..4d534582514e 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -19,6 +19,8 @@
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>
23#include <linux/tick.h>
22#include <trace/events/power.h> 24#include <trace/events/power.h>
23 25
24#include "cpuidle.h" 26#include "cpuidle.h"
@@ -32,7 +34,6 @@ LIST_HEAD(cpuidle_detected_devices);
32static int enabled_devices; 34static int enabled_devices;
33static int off __read_mostly; 35static int off __read_mostly;
34static int initialized __read_mostly; 36static int initialized __read_mostly;
35static bool use_deepest_state __read_mostly;
36 37
37int cpuidle_disabled(void) 38int cpuidle_disabled(void)
38{ 39{
@@ -66,36 +67,23 @@ int cpuidle_play_dead(void)
66} 67}
67 68
68/** 69/**
69 * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode. 70 * cpuidle_find_deepest_state - Find deepest state meeting specific conditions.
70 * @enable: Whether enable or disable the feature. 71 * @drv: cpuidle driver for the given CPU.
71 * 72 * @dev: cpuidle device for the given CPU.
72 * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and 73 * @freeze: Whether or not the state should be suitable for suspend-to-idle.
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 */ 74 */
88static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, 75static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
89 struct cpuidle_device *dev) 76 struct cpuidle_device *dev, bool freeze)
90{ 77{
91 unsigned int latency_req = 0; 78 unsigned int latency_req = 0;
92 int i, ret = CPUIDLE_DRIVER_STATE_START - 1; 79 int i, ret = freeze ? -1 : CPUIDLE_DRIVER_STATE_START - 1;
93 80
94 for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { 81 for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
95 struct cpuidle_state *s = &drv->states[i]; 82 struct cpuidle_state *s = &drv->states[i];
96 struct cpuidle_state_usage *su = &dev->states_usage[i]; 83 struct cpuidle_state_usage *su = &dev->states_usage[i];
97 84
98 if (s->disabled || su->disable || s->exit_latency <= latency_req) 85 if (s->disabled || su->disable || s->exit_latency <= latency_req
86 || (freeze && !s->enter_freeze))
99 continue; 87 continue;
100 88
101 latency_req = s->exit_latency; 89 latency_req = s->exit_latency;
@@ -104,6 +92,63 @@ static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
104 return ret; 92 return ret;
105} 93}
106 94
95static void enter_freeze_proper(struct cpuidle_driver *drv,
96 struct cpuidle_device *dev, int index)
97{
98 tick_freeze();
99 /*
100 * The state used here cannot be a "coupled" one, because the "coupled"
101 * cpuidle mechanism enables interrupts and doing that with timekeeping
102 * suspended is generally unsafe.
103 */
104 drv->states[index].enter_freeze(dev, drv, index);
105 WARN_ON(!irqs_disabled());
106 /*
107 * timekeeping_resume() that will be called by tick_unfreeze() for the
108 * last CPU executing it calls functions containing RCU read-side
109 * critical sections, so tell RCU about that.
110 */
111 RCU_NONIDLE(tick_unfreeze());
112}
113
114/**
115 * cpuidle_enter_freeze - Enter an idle state suitable for suspend-to-idle.
116 *
117 * If there are states with the ->enter_freeze callback, find the deepest of
118 * them and enter it with frozen tick. Otherwise, find the deepest state
119 * available and enter it normally.
120 */
121void cpuidle_enter_freeze(void)
122{
123 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
124 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
125 int index;
126
127 /*
128 * Find the deepest state with ->enter_freeze present, which guarantees
129 * that interrupts won't be enabled when it exits and allows the tick to
130 * be frozen safely.
131 */
132 index = cpuidle_find_deepest_state(drv, dev, true);
133 if (index >= 0) {
134 enter_freeze_proper(drv, dev, index);
135 return;
136 }
137
138 /*
139 * It is not safe to freeze the tick, find the deepest state available
140 * at all and try to enter it normally.
141 */
142 index = cpuidle_find_deepest_state(drv, dev, false);
143 if (index >= 0)
144 cpuidle_enter(drv, dev, index);
145 else
146 arch_cpu_idle();
147
148 /* Interrupts are enabled again here. */
149 local_irq_disable();
150}
151
107/** 152/**
108 * cpuidle_enter_state - enter the state and update stats 153 * cpuidle_enter_state - enter the state and update stats
109 * @dev: cpuidle device for this cpu 154 * @dev: cpuidle device for this cpu
@@ -166,9 +211,6 @@ int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
166 if (!drv || !dev || !dev->enabled) 211 if (!drv || !dev || !dev->enabled)
167 return -EBUSY; 212 return -EBUSY;
168 213
169 if (unlikely(use_deepest_state))
170 return cpuidle_find_deepest_state(drv, dev);
171
172 return cpuidle_curr_governor->select(drv, dev); 214 return cpuidle_curr_governor->select(drv, dev);
173} 215}
174 216
@@ -200,7 +242,7 @@ int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev,
200 */ 242 */
201void cpuidle_reflect(struct cpuidle_device *dev, int index) 243void cpuidle_reflect(struct cpuidle_device *dev, int index)
202{ 244{
203 if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state)) 245 if (cpuidle_curr_governor->reflect)
204 cpuidle_curr_governor->reflect(dev, index); 246 cpuidle_curr_governor->reflect(dev, index);
205} 247}
206 248