aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/cpuidle.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-07 13:13:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-07 13:13:52 -0500
commit3c00303206c3a1ccd86579efdc90bc35f140962e (patch)
tree66170c84b5ddaeb102aea3530517a26657b6ea29 /drivers/cpuidle/cpuidle.c
parent83dbb15e9cd78a3619e3db36777e2f81d09b2914 (diff)
parentefb90582c575084723cc14302c1300cb26c7e01f (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: cpuidle: Single/Global registration of idle states cpuidle: Split cpuidle_state structure and move per-cpu statistics fields cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev->prepare() cpuidle: Move dev->last_residency update to driver enter routine; remove dev->last_state ACPI: Fix CONFIG_ACPI_DOCK=n compiler warning ACPI: Export FADT pm_profile integer value to userspace thermal: Prevent polling from happening during system suspend ACPI: Drop ACPI_NO_HARDWARE_INIT ACPI atomicio: Convert width in bits to bytes in __acpi_ioremap_fast() PNPACPI: Simplify disabled resource registration ACPI: Fix possible recursive locking in hwregs.c ACPI: use kstrdup() mrst pmu: update comment tools/power turbostat: less verbose debugging
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r--drivers/cpuidle/cpuidle.c86
1 files changed, 28 insertions, 58 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index becd6d99203b..06ce2680d00d 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -62,8 +62,9 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
62int cpuidle_idle_call(void) 62int cpuidle_idle_call(void)
63{ 63{
64 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); 64 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
65 struct cpuidle_driver *drv = cpuidle_get_driver();
65 struct cpuidle_state *target_state; 66 struct cpuidle_state *target_state;
66 int next_state; 67 int next_state, entered_state;
67 68
68 if (off) 69 if (off)
69 return -ENODEV; 70 return -ENODEV;
@@ -84,45 +85,36 @@ int cpuidle_idle_call(void)
84 hrtimer_peek_ahead_timers(); 85 hrtimer_peek_ahead_timers();
85#endif 86#endif
86 87
87 /*
88 * Call the device's prepare function before calling the
89 * governor's select function. ->prepare gives the device's
90 * cpuidle driver a chance to update any dynamic information
91 * of its cpuidle states for the current idle period, e.g.
92 * state availability, latencies, residencies, etc.
93 */
94 if (dev->prepare)
95 dev->prepare(dev);
96
97 /* ask the governor for the next state */ 88 /* ask the governor for the next state */
98 next_state = cpuidle_curr_governor->select(dev); 89 next_state = cpuidle_curr_governor->select(drv, dev);
99 if (need_resched()) { 90 if (need_resched()) {
100 local_irq_enable(); 91 local_irq_enable();
101 return 0; 92 return 0;
102 } 93 }
103 94
104 target_state = &dev->states[next_state]; 95 target_state = &drv->states[next_state];
105
106 /* enter the state and update stats */
107 dev->last_state = target_state;
108 96
109 trace_power_start(POWER_CSTATE, next_state, dev->cpu); 97 trace_power_start(POWER_CSTATE, next_state, dev->cpu);
110 trace_cpu_idle(next_state, dev->cpu); 98 trace_cpu_idle(next_state, dev->cpu);
111 99
112 dev->last_residency = target_state->enter(dev, target_state); 100 entered_state = target_state->enter(dev, drv, next_state);
113 101
114 trace_power_end(dev->cpu); 102 trace_power_end(dev->cpu);
115 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); 103 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
116 104
117 if (dev->last_state) 105 if (entered_state >= 0) {
118 target_state = dev->last_state; 106 /* Update cpuidle counters */
119 107 /* This can be moved to within driver enter routine
120 target_state->time += (unsigned long long)dev->last_residency; 108 * but that results in multiple copies of same code.
121 target_state->usage++; 109 */
110 dev->states_usage[entered_state].time +=
111 (unsigned long long)dev->last_residency;
112 dev->states_usage[entered_state].usage++;
113 }
122 114
123 /* give the governor an opportunity to reflect on the outcome */ 115 /* give the governor an opportunity to reflect on the outcome */
124 if (cpuidle_curr_governor->reflect) 116 if (cpuidle_curr_governor->reflect)
125 cpuidle_curr_governor->reflect(dev); 117 cpuidle_curr_governor->reflect(dev, entered_state);
126 118
127 return 0; 119 return 0;
128} 120}
@@ -173,11 +165,11 @@ void cpuidle_resume_and_unlock(void)
173EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); 165EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
174 166
175#ifdef CONFIG_ARCH_HAS_CPU_RELAX 167#ifdef CONFIG_ARCH_HAS_CPU_RELAX
176static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) 168static int poll_idle(struct cpuidle_device *dev,
169 struct cpuidle_driver *drv, int index)
177{ 170{
178 ktime_t t1, t2; 171 ktime_t t1, t2;
179 s64 diff; 172 s64 diff;
180 int ret;
181 173
182 t1 = ktime_get(); 174 t1 = ktime_get();
183 local_irq_enable(); 175 local_irq_enable();
@@ -189,15 +181,14 @@ static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
189 if (diff > INT_MAX) 181 if (diff > INT_MAX)
190 diff = INT_MAX; 182 diff = INT_MAX;
191 183
192 ret = (int) diff; 184 dev->last_residency = (int) diff;
193 return ret; 185
186 return index;
194} 187}
195 188
196static void poll_idle_init(struct cpuidle_device *dev) 189static void poll_idle_init(struct cpuidle_driver *drv)
197{ 190{
198 struct cpuidle_state *state = &dev->states[0]; 191 struct cpuidle_state *state = &drv->states[0];
199
200 cpuidle_set_statedata(state, NULL);
201 192
202 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); 193 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
203 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); 194 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -208,7 +199,7 @@ static void poll_idle_init(struct cpuidle_device *dev)
208 state->enter = poll_idle; 199 state->enter = poll_idle;
209} 200}
210#else 201#else
211static void poll_idle_init(struct cpuidle_device *dev) {} 202static void poll_idle_init(struct cpuidle_driver *drv) {}
212#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ 203#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
213 204
214/** 205/**
@@ -235,21 +226,20 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
235 return ret; 226 return ret;
236 } 227 }
237 228
238 poll_idle_init(dev); 229 poll_idle_init(cpuidle_get_driver());
239 230
240 if ((ret = cpuidle_add_state_sysfs(dev))) 231 if ((ret = cpuidle_add_state_sysfs(dev)))
241 return ret; 232 return ret;
242 233
243 if (cpuidle_curr_governor->enable && 234 if (cpuidle_curr_governor->enable &&
244 (ret = cpuidle_curr_governor->enable(dev))) 235 (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
245 goto fail_sysfs; 236 goto fail_sysfs;
246 237
247 for (i = 0; i < dev->state_count; i++) { 238 for (i = 0; i < dev->state_count; i++) {
248 dev->states[i].usage = 0; 239 dev->states_usage[i].usage = 0;
249 dev->states[i].time = 0; 240 dev->states_usage[i].time = 0;
250 } 241 }
251 dev->last_residency = 0; 242 dev->last_residency = 0;
252 dev->last_state = NULL;
253 243
254 smp_wmb(); 244 smp_wmb();
255 245
@@ -283,7 +273,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
283 dev->enabled = 0; 273 dev->enabled = 0;
284 274
285 if (cpuidle_curr_governor->disable) 275 if (cpuidle_curr_governor->disable)
286 cpuidle_curr_governor->disable(dev); 276 cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
287 277
288 cpuidle_remove_state_sysfs(dev); 278 cpuidle_remove_state_sysfs(dev);
289 enabled_devices--; 279 enabled_devices--;
@@ -311,26 +301,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
311 301
312 init_completion(&dev->kobj_unregister); 302 init_completion(&dev->kobj_unregister);
313 303
314 /*
315 * cpuidle driver should set the dev->power_specified bit
316 * before registering the device if the driver provides
317 * power_usage numbers.
318 *
319 * For those devices whose ->power_specified is not set,
320 * we fill in power_usage with decreasing values as the
321 * cpuidle code has an implicit assumption that state Cn
322 * uses less power than C(n-1).
323 *
324 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
325 * an power value of -1. So we use -2, -3, etc, for other
326 * c-states.
327 */
328 if (!dev->power_specified) {
329 int i;
330 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
331 dev->states[i].power_usage = -1 - i;
332 }
333
334 per_cpu(cpuidle_devices, dev->cpu) = dev; 304 per_cpu(cpuidle_devices, dev->cpu) = dev;
335 list_add(&dev->device_list, &cpuidle_detected_devices); 305 list_add(&dev->device_list, &cpuidle_detected_devices);
336 if ((ret = cpuidle_add_sysfs(sys_dev))) { 306 if ((ret = cpuidle_add_sysfs(sys_dev))) {