blob: c50037029184b1e507690d133cd2ef87aa8c2c05 [file] [log] [blame]
Len Brown4f86d3a2007-10-03 18:58:00 -04001/*
2 * cpuidle.c - core cpuidle infrastructure
3 *
4 * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
5 * Shaohua Li <shaohua.li@intel.com>
6 * Adam Belay <abelay@novell.com>
7 *
8 * This code is licenced under the GPL.
9 */
10
Daniel Lezcanob60e6a02013-03-21 12:21:31 +000011#include <linux/clockchips.h>
Len Brown4f86d3a2007-10-03 18:58:00 -040012#include <linux/kernel.h>
13#include <linux/mutex.h>
14#include <linux/sched.h>
15#include <linux/notifier.h>
Jean Pihete8db0be2011-08-25 15:35:03 +020016#include <linux/pm_qos.h>
Len Brown4f86d3a2007-10-03 18:58:00 -040017#include <linux/cpu.h>
18#include <linux/cpuidle.h>
venkatesh.pallipadi@intel.com9a0b8412008-01-31 17:35:06 -080019#include <linux/ktime.h>
Arjan van de Ven2e94d1f2008-09-10 16:06:00 -070020#include <linux/hrtimer.h>
Paul Gortmaker884b17e2011-08-29 17:52:39 -040021#include <linux/module.h>
Arjan van de Ven288f0232009-09-19 13:35:33 +020022#include <trace/events/power.h>
Len Brown4f86d3a2007-10-03 18:58:00 -040023
24#include "cpuidle.h"
25
26DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
Len Brown4f86d3a2007-10-03 18:58:00 -040027
28DEFINE_MUTEX(cpuidle_lock);
29LIST_HEAD(cpuidle_detected_devices);
Len Brown4f86d3a2007-10-03 18:58:00 -040030
31static int enabled_devices;
Len Brown62027ae2011-04-01 18:13:10 -040032static int off __read_mostly;
Len Browna0bfa132011-04-01 19:34:59 -040033static int initialized __read_mostly;
Len Brown62027ae2011-04-01 18:13:10 -040034
35int cpuidle_disabled(void)
36{
37 return off;
38}
Len Brownd91ee582011-04-01 18:28:35 -040039void disable_cpuidle(void)
40{
41 off = 1;
42}
Len Brown4f86d3a2007-10-03 18:58:00 -040043
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -040044static int __cpuidle_register_device(struct cpuidle_device *dev);
45
Robert Leee1689792012-03-20 15:22:42 -050046static inline int cpuidle_enter(struct cpuidle_device *dev,
47 struct cpuidle_driver *drv, int index)
48{
49 struct cpuidle_state *target_state = &drv->states[index];
50 return target_state->enter(dev, drv, index);
51}
52
53static inline int cpuidle_enter_tk(struct cpuidle_device *dev,
54 struct cpuidle_driver *drv, int index)
55{
56 return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter);
57}
58
59typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev,
60 struct cpuidle_driver *drv, int index);
61
62static cpuidle_enter_t cpuidle_enter_ops;
63
Len Brown4f86d3a2007-10-03 18:58:00 -040064/**
Boris Ostrovsky1a022e32012-03-13 19:55:09 +010065 * cpuidle_play_dead - cpu off-lining
66 *
Toshi Kaniee01e662012-03-31 21:37:02 -060067 * Returns in case of an error or no driver
Boris Ostrovsky1a022e32012-03-13 19:55:09 +010068 */
69int cpuidle_play_dead(void)
70{
71 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +000072 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
Daniel Lezcano8aef33a2013-01-15 14:18:04 +010073 int i;
Boris Ostrovsky1a022e32012-03-13 19:55:09 +010074
Toshi Kaniee01e662012-03-31 21:37:02 -060075 if (!drv)
76 return -ENODEV;
77
Boris Ostrovsky1a022e32012-03-13 19:55:09 +010078 /* Find lowest-power state that supports long-term idle */
Daniel Lezcano8aef33a2013-01-15 14:18:04 +010079 for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--)
80 if (drv->states[i].enter_dead)
81 return drv->states[i].enter_dead(dev, i);
Boris Ostrovsky1a022e32012-03-13 19:55:09 +010082
83 return -ENODEV;
84}
85
86/**
Colin Cross56cfbf72012-05-07 17:57:39 -070087 * cpuidle_enter_state - enter the state and update stats
88 * @dev: cpuidle device for this cpu
89 * @drv: cpuidle driver for this cpu
90 * @next_state: index into drv->states of the state to enter
91 */
92int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
93 int next_state)
94{
95 int entered_state;
96
97 entered_state = cpuidle_enter_ops(dev, drv, next_state);
98
99 if (entered_state >= 0) {
100 /* Update cpuidle counters */
101 /* This can be moved to within driver enter routine
102 * but that results in multiple copies of same code.
103 */
Julius Wernera474a512012-11-27 14:17:58 +0100104 dev->states_usage[entered_state].time += dev->last_residency;
Colin Cross56cfbf72012-05-07 17:57:39 -0700105 dev->states_usage[entered_state].usage++;
106 } else {
107 dev->last_residency = 0;
108 }
109
110 return entered_state;
111}
112
113/**
Len Brown4f86d3a2007-10-03 18:58:00 -0400114 * cpuidle_idle_call - the main idle loop
115 *
116 * NOTE: no locks or semaphores should be used here
Len Browna0bfa132011-04-01 19:34:59 -0400117 * return non-zero on failure
Len Brown4f86d3a2007-10-03 18:58:00 -0400118 */
Len Browna0bfa132011-04-01 19:34:59 -0400119int cpuidle_idle_call(void)
Len Brown4f86d3a2007-10-03 18:58:00 -0400120{
Christoph Lameter4a6f4fe2010-12-06 11:16:24 -0600121 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000122 struct cpuidle_driver *drv;
Deepthi Dharware978aa72011-10-28 16:20:09 +0530123 int next_state, entered_state;
Len Brown4f86d3a2007-10-03 18:58:00 -0400124
Len Browna0bfa132011-04-01 19:34:59 -0400125 if (off)
126 return -ENODEV;
127
128 if (!initialized)
129 return -ENODEV;
130
Len Brown4f86d3a2007-10-03 18:58:00 -0400131 /* check if the device is ready */
Len Browna0bfa132011-04-01 19:34:59 -0400132 if (!dev || !dev->enabled)
133 return -EBUSY;
Len Brown4f86d3a2007-10-03 18:58:00 -0400134
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000135 drv = cpuidle_get_cpu_driver(dev);
136
Len Brown4f86d3a2007-10-03 18:58:00 -0400137 /* ask the governor for the next state */
Deepthi Dharwar46bcfad2011-10-28 16:20:42 +0530138 next_state = cpuidle_curr_governor->select(drv, dev);
Kevin Hilman246eb7f2009-10-26 16:50:18 -0700139 if (need_resched()) {
Youquan Songd73d68d2012-10-26 12:26:59 +0200140 dev->last_residency = 0;
141 /* give the governor an opportunity to reflect on the outcome */
142 if (cpuidle_curr_governor->reflect)
143 cpuidle_curr_governor->reflect(dev, next_state);
Kevin Hilman246eb7f2009-10-26 16:50:18 -0700144 local_irq_enable();
Len Browna0bfa132011-04-01 19:34:59 -0400145 return 0;
Kevin Hilman246eb7f2009-10-26 16:50:18 -0700146 }
147
Steven Rostedt76027ea2012-02-07 09:46:01 -0500148 trace_cpu_idle_rcuidle(next_state, dev->cpu);
Thomas Renningerf77cfe42011-01-07 11:29:44 +0100149
Daniel Lezcanob60e6a02013-03-21 12:21:31 +0000150 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
151 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
152 &dev->cpu);
153
Colin Cross4126c012012-05-07 17:57:41 -0700154 if (cpuidle_state_is_coupled(dev, drv, next_state))
155 entered_state = cpuidle_enter_state_coupled(dev, drv,
156 next_state);
157 else
158 entered_state = cpuidle_enter_state(dev, drv, next_state);
Thomas Renningerf77cfe42011-01-07 11:29:44 +0100159
Daniel Lezcanob60e6a02013-03-21 12:21:31 +0000160 if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
161 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
162 &dev->cpu);
163
Steven Rostedt76027ea2012-02-07 09:46:01 -0500164 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
Thomas Renningerf77cfe42011-01-07 11:29:44 +0100165
Len Brown4f86d3a2007-10-03 18:58:00 -0400166 /* give the governor an opportunity to reflect on the outcome */
167 if (cpuidle_curr_governor->reflect)
Deepthi Dharware978aa72011-10-28 16:20:09 +0530168 cpuidle_curr_governor->reflect(dev, entered_state);
Len Browna0bfa132011-04-01 19:34:59 -0400169
170 return 0;
Len Brown4f86d3a2007-10-03 18:58:00 -0400171}
172
173/**
174 * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
175 */
176void cpuidle_install_idle_handler(void)
177{
Len Browna0bfa132011-04-01 19:34:59 -0400178 if (enabled_devices) {
Len Brown4f86d3a2007-10-03 18:58:00 -0400179 /* Make sure all changes finished before we switch to new idle */
180 smp_wmb();
Len Browna0bfa132011-04-01 19:34:59 -0400181 initialized = 1;
Len Brown4f86d3a2007-10-03 18:58:00 -0400182 }
183}
184
185/**
186 * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
187 */
188void cpuidle_uninstall_idle_handler(void)
189{
Len Browna0bfa132011-04-01 19:34:59 -0400190 if (enabled_devices) {
191 initialized = 0;
Thomas Gleixner4a162512012-05-07 17:59:48 +0000192 kick_all_cpus_sync();
Len Brown4f86d3a2007-10-03 18:58:00 -0400193 }
194}
195
196/**
197 * cpuidle_pause_and_lock - temporarily disables CPUIDLE
198 */
199void cpuidle_pause_and_lock(void)
200{
201 mutex_lock(&cpuidle_lock);
202 cpuidle_uninstall_idle_handler();
203}
204
205EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock);
206
207/**
208 * cpuidle_resume_and_unlock - resumes CPUIDLE operation
209 */
210void cpuidle_resume_and_unlock(void)
211{
212 cpuidle_install_idle_handler();
213 mutex_unlock(&cpuidle_lock);
214}
215
216EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
217
Preeti U Murthy8651f972012-07-09 10:12:56 +0200218/* Currently used in suspend/resume path to suspend cpuidle */
219void cpuidle_pause(void)
220{
221 mutex_lock(&cpuidle_lock);
222 cpuidle_uninstall_idle_handler();
223 mutex_unlock(&cpuidle_lock);
224}
225
226/* Currently used in suspend/resume path to resume cpuidle */
227void cpuidle_resume(void)
228{
229 mutex_lock(&cpuidle_lock);
230 cpuidle_install_idle_handler();
231 mutex_unlock(&cpuidle_lock);
232}
233
Robert Leee1689792012-03-20 15:22:42 -0500234/**
235 * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
236 * @dev: pointer to a valid cpuidle_device object
237 * @drv: pointer to a valid cpuidle_driver object
238 * @index: index of the target cpuidle state.
239 */
240int cpuidle_wrap_enter(struct cpuidle_device *dev,
241 struct cpuidle_driver *drv, int index,
242 int (*enter)(struct cpuidle_device *dev,
243 struct cpuidle_driver *drv, int index))
244{
245 ktime_t time_start, time_end;
246 s64 diff;
247
248 time_start = ktime_get();
249
250 index = enter(dev, drv, index);
251
252 time_end = ktime_get();
253
254 local_irq_enable();
255
256 diff = ktime_to_us(ktime_sub(time_end, time_start));
257 if (diff > INT_MAX)
258 diff = INT_MAX;
259
260 dev->last_residency = (int) diff;
261
262 return index;
263}
264
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100265#ifdef CONFIG_ARCH_HAS_CPU_RELAX
Deepthi Dharwar46bcfad2011-10-28 16:20:42 +0530266static int poll_idle(struct cpuidle_device *dev,
267 struct cpuidle_driver *drv, int index)
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100268{
269 ktime_t t1, t2;
270 s64 diff;
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100271
272 t1 = ktime_get();
273 local_irq_enable();
274 while (!need_resched())
275 cpu_relax();
276
277 t2 = ktime_get();
278 diff = ktime_to_us(ktime_sub(t2, t1));
279 if (diff > INT_MAX)
280 diff = INT_MAX;
281
Deepthi Dharware978aa72011-10-28 16:20:09 +0530282 dev->last_residency = (int) diff;
283
284 return index;
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100285}
286
Deepthi Dharwar46bcfad2011-10-28 16:20:42 +0530287static void poll_idle_init(struct cpuidle_driver *drv)
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100288{
Deepthi Dharwar46bcfad2011-10-28 16:20:42 +0530289 struct cpuidle_state *state = &drv->states[0];
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100290
Thomas Renninger720f1c32011-01-07 11:29:43 +0100291 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100292 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
293 state->exit_latency = 0;
294 state->target_residency = 0;
295 state->power_usage = -1;
Len Brownd2476322011-01-12 02:34:59 -0500296 state->flags = 0;
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100297 state->enter = poll_idle;
Rafael J. Wysockicbc9ef02012-07-03 19:07:42 +0200298 state->disabled = false;
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100299}
300#else
Deepthi Dharwar46bcfad2011-10-28 16:20:42 +0530301static void poll_idle_init(struct cpuidle_driver *drv) {}
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100302#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
303
Len Brown4f86d3a2007-10-03 18:58:00 -0400304/**
305 * cpuidle_enable_device - enables idle PM for a CPU
306 * @dev: the CPU
307 *
308 * This function must be called between cpuidle_pause_and_lock and
309 * cpuidle_resume_and_unlock when used externally.
310 */
311int cpuidle_enable_device(struct cpuidle_device *dev)
312{
313 int ret, i;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000314 struct cpuidle_driver *drv;
Len Brown4f86d3a2007-10-03 18:58:00 -0400315
Srivatsa S. Bhat1b0a0e92012-05-04 14:06:02 -0700316 if (!dev)
317 return -EINVAL;
318
Len Brown4f86d3a2007-10-03 18:58:00 -0400319 if (dev->enabled)
320 return 0;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000321
322 drv = cpuidle_get_cpu_driver(dev);
323
Robert Leee1689792012-03-20 15:22:42 -0500324 if (!drv || !cpuidle_curr_governor)
Len Brown4f86d3a2007-10-03 18:58:00 -0400325 return -EIO;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000326
Len Brown4f86d3a2007-10-03 18:58:00 -0400327 if (!dev->state_count)
Daniel Lezcanofc850f32012-03-26 14:51:26 +0200328 dev->state_count = drv->state_count;
Len Brown4f86d3a2007-10-03 18:58:00 -0400329
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400330 if (dev->registered == 0) {
331 ret = __cpuidle_register_device(dev);
332 if (ret)
333 return ret;
334 }
335
Robert Leee1689792012-03-20 15:22:42 -0500336 cpuidle_enter_ops = drv->en_core_tk_irqen ?
337 cpuidle_enter_tk : cpuidle_enter;
338
339 poll_idle_init(drv);
Rafael J. Wysockid8c216c2011-01-08 00:29:20 +0100340
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000341 ret = cpuidle_add_device_sysfs(dev);
342 if (ret)
Len Brown4f86d3a2007-10-03 18:58:00 -0400343 return ret;
344
345 if (cpuidle_curr_governor->enable &&
Robert Leee1689792012-03-20 15:22:42 -0500346 (ret = cpuidle_curr_governor->enable(drv, dev)))
Len Brown4f86d3a2007-10-03 18:58:00 -0400347 goto fail_sysfs;
348
349 for (i = 0; i < dev->state_count; i++) {
Deepthi Dharwar42027352011-10-28 16:20:33 +0530350 dev->states_usage[i].usage = 0;
351 dev->states_usage[i].time = 0;
Len Brown4f86d3a2007-10-03 18:58:00 -0400352 }
353 dev->last_residency = 0;
Len Brown4f86d3a2007-10-03 18:58:00 -0400354
355 smp_wmb();
356
357 dev->enabled = 1;
358
359 enabled_devices++;
360 return 0;
361
362fail_sysfs:
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000363 cpuidle_remove_device_sysfs(dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400364
365 return ret;
366}
367
368EXPORT_SYMBOL_GPL(cpuidle_enable_device);
369
370/**
371 * cpuidle_disable_device - disables idle PM for a CPU
372 * @dev: the CPU
373 *
374 * This function must be called between cpuidle_pause_and_lock and
375 * cpuidle_resume_and_unlock when used externally.
376 */
377void cpuidle_disable_device(struct cpuidle_device *dev)
378{
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000379 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
380
Srivatsa S. Bhatcf31cd12012-10-08 13:43:08 +0530381 if (!dev || !dev->enabled)
Len Brown4f86d3a2007-10-03 18:58:00 -0400382 return;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000383
384 if (!drv || !cpuidle_curr_governor)
Len Brown4f86d3a2007-10-03 18:58:00 -0400385 return;
386
387 dev->enabled = 0;
388
389 if (cpuidle_curr_governor->disable)
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000390 cpuidle_curr_governor->disable(drv, dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400391
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000392 cpuidle_remove_device_sysfs(dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400393 enabled_devices--;
394}
395
396EXPORT_SYMBOL_GPL(cpuidle_disable_device);
397
398/**
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400399 * __cpuidle_register_device - internal register function called before register
400 * and enable routines
Len Brown4f86d3a2007-10-03 18:58:00 -0400401 * @dev: the cpu
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400402 *
403 * cpuidle_lock mutex must be held before this is called
Len Brown4f86d3a2007-10-03 18:58:00 -0400404 */
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400405static int __cpuidle_register_device(struct cpuidle_device *dev)
Len Brown4f86d3a2007-10-03 18:58:00 -0400406{
407 int ret;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000408 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400409
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000410 if (!try_module_get(drv->owner))
Len Brown4f86d3a2007-10-03 18:58:00 -0400411 return -EINVAL;
412
Len Brown4f86d3a2007-10-03 18:58:00 -0400413 per_cpu(cpuidle_devices, dev->cpu) = dev;
414 list_add(&dev->device_list, &cpuidle_detected_devices);
Daniel Lezcano1aef40e2012-10-26 12:26:24 +0200415 ret = cpuidle_add_sysfs(dev);
Colin Cross3af272a2012-05-07 17:57:40 -0700416 if (ret)
417 goto err_sysfs;
Len Brown4f86d3a2007-10-03 18:58:00 -0400418
Colin Cross4126c012012-05-07 17:57:41 -0700419 ret = cpuidle_coupled_register_device(dev);
420 if (ret)
421 goto err_coupled;
Len Brown4f86d3a2007-10-03 18:58:00 -0400422
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400423 dev->registered = 1;
424 return 0;
Colin Cross3af272a2012-05-07 17:57:40 -0700425
Colin Cross4126c012012-05-07 17:57:41 -0700426err_coupled:
Daniel Lezcano1aef40e2012-10-26 12:26:24 +0200427 cpuidle_remove_sysfs(dev);
Colin Cross3af272a2012-05-07 17:57:40 -0700428err_sysfs:
429 list_del(&dev->device_list);
430 per_cpu(cpuidle_devices, dev->cpu) = NULL;
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000431 module_put(drv->owner);
Colin Cross3af272a2012-05-07 17:57:40 -0700432 return ret;
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400433}
434
435/**
436 * cpuidle_register_device - registers a CPU's idle PM feature
437 * @dev: the cpu
438 */
439int cpuidle_register_device(struct cpuidle_device *dev)
440{
441 int ret;
442
Srivatsa S. Bhat1b0a0e92012-05-04 14:06:02 -0700443 if (!dev)
444 return -EINVAL;
445
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400446 mutex_lock(&cpuidle_lock);
447
448 if ((ret = __cpuidle_register_device(dev))) {
449 mutex_unlock(&cpuidle_lock);
450 return ret;
451 }
452
Len Brown4f86d3a2007-10-03 18:58:00 -0400453 cpuidle_enable_device(dev);
454 cpuidle_install_idle_handler();
455
456 mutex_unlock(&cpuidle_lock);
457
458 return 0;
459
460}
461
462EXPORT_SYMBOL_GPL(cpuidle_register_device);
463
464/**
465 * cpuidle_unregister_device - unregisters a CPU's idle PM feature
466 * @dev: the cpu
467 */
468void cpuidle_unregister_device(struct cpuidle_device *dev)
469{
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000470 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400471
Venkatesh Pallipadidcb84f32008-05-19 19:09:27 -0400472 if (dev->registered == 0)
473 return;
474
Len Brown4f86d3a2007-10-03 18:58:00 -0400475 cpuidle_pause_and_lock();
476
477 cpuidle_disable_device(dev);
478
Daniel Lezcano1aef40e2012-10-26 12:26:24 +0200479 cpuidle_remove_sysfs(dev);
Len Brown4f86d3a2007-10-03 18:58:00 -0400480 list_del(&dev->device_list);
Len Brown4f86d3a2007-10-03 18:58:00 -0400481 per_cpu(cpuidle_devices, dev->cpu) = NULL;
482
Colin Cross4126c012012-05-07 17:57:41 -0700483 cpuidle_coupled_unregister_device(dev);
484
Len Brown4f86d3a2007-10-03 18:58:00 -0400485 cpuidle_resume_and_unlock();
486
Daniel Lezcanobf4d1b52012-10-31 16:44:48 +0000487 module_put(drv->owner);
Len Brown4f86d3a2007-10-03 18:58:00 -0400488}
489
490EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
491
492#ifdef CONFIG_SMP
493
494static void smp_callback(void *v)
495{
496 /* we already woke the CPU up, nothing more to do */
497}
498
499/*
500 * This function gets called when a part of the kernel has a new latency
501 * requirement. This means we need to get all processors out of their C-state,
502 * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
503 * wakes them all right up.
504 */
505static int cpuidle_latency_notify(struct notifier_block *b,
506 unsigned long l, void *v)
507{
Jens Axboe8691e5a2008-06-06 11:18:06 +0200508 smp_call_function(smp_callback, NULL, 1);
Len Brown4f86d3a2007-10-03 18:58:00 -0400509 return NOTIFY_OK;
510}
511
512static struct notifier_block cpuidle_latency_notifier = {
513 .notifier_call = cpuidle_latency_notify,
514};
515
Mark Grossd82b3512008-02-04 22:30:08 -0800516static inline void latency_notifier_init(struct notifier_block *n)
517{
518 pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, n);
519}
Len Brown4f86d3a2007-10-03 18:58:00 -0400520
521#else /* CONFIG_SMP */
522
523#define latency_notifier_init(x) do { } while (0)
524
525#endif /* CONFIG_SMP */
526
527/**
528 * cpuidle_init - core initializer
529 */
530static int __init cpuidle_init(void)
531{
532 int ret;
533
Len Brown62027ae2011-04-01 18:13:10 -0400534 if (cpuidle_disabled())
535 return -ENODEV;
536
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800537 ret = cpuidle_add_interface(cpu_subsys.dev_root);
Len Brown4f86d3a2007-10-03 18:58:00 -0400538 if (ret)
539 return ret;
540
541 latency_notifier_init(&cpuidle_latency_notifier);
542
543 return 0;
544}
545
Len Brown62027ae2011-04-01 18:13:10 -0400546module_param(off, int, 0444);
Len Brown4f86d3a2007-10-03 18:58:00 -0400547core_initcall(cpuidle_init);