aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/cpuidle.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 17:28:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 17:28:55 -0400
commit476525004ac7e2f990b6956efcd44d0780c2ab4c (patch)
tree158cd2bbfb232b4f4327b6c20a4e14c6b095a438 /drivers/cpuidle/cpuidle.c
parentbd22dc17e49973d3d4925970260e9e37f7580a9f (diff)
parentec033d0a02901551346b9f43f8ff9bad51378891 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
Pull ACPI & power management update from Len Brown: "Re-write of the turbostat tool. lower overhead was necessary for measuring very large system when they are very idle. IVB support in intel_idle It's what I run on my IVB, others should be able to also:-) ACPICA core update We have found some bugs due to divergence between Linux and the upstream ACPICA base. Most of these patches are to reduce that divergence to reduce the risk of future bugs. Some cpuidle updates, mostly for non-Intel More will be coming, as they depend on this part. Some thermal management changes needed by non-ACPI systems. Some _OST (OS Status Indication) updates for hot ACPI hot-plug." * 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: (51 commits) Thermal: Documentation update Thermal: Add Hysteresis attributes Thermal: Make Thermal trip points writeable ACPI/AC: prevent OOPS on some boxes due to missing check power_supply_register() return value check tools/power: turbostat: fix large c1% issue tools/power: turbostat v2 - re-write for efficiency ACPICA: Update to version 20120711 ACPICA: AcpiSrc: Fix some translation issues for Linux conversion ACPICA: Update header files copyrights to 2012 ACPICA: Add new ACPI table load/unload external interfaces ACPICA: Split file: tbxface.c -> tbxfload.c ACPICA: Add PCC address space to space ID decode function ACPICA: Fix some comment fields ACPICA: Table manager: deploy new firmware error/warning interfaces ACPICA: Add new interfaces for BIOS(firmware) errors and warnings ACPICA: Split exception code utilities to a new file, utexcep.c ACPI: acpi_pad: tune round_robin_time ACPICA: Update to version 20120620 ACPICA: Add support for implicit notify on multiple devices ACPICA: Update comments; no functional change ...
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r--drivers/cpuidle/cpuidle.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index d6a533e68e0f..e28f6ea46f1a 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -92,6 +92,34 @@ int cpuidle_play_dead(void)
92} 92}
93 93
94/** 94/**
95 * cpuidle_enter_state - enter the state and update stats
96 * @dev: cpuidle device for this cpu
97 * @drv: cpuidle driver for this cpu
98 * @next_state: index into drv->states of the state to enter
99 */
100int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
101 int next_state)
102{
103 int entered_state;
104
105 entered_state = cpuidle_enter_ops(dev, drv, next_state);
106
107 if (entered_state >= 0) {
108 /* Update cpuidle counters */
109 /* This can be moved to within driver enter routine
110 * but that results in multiple copies of same code.
111 */
112 dev->states_usage[entered_state].time +=
113 (unsigned long long)dev->last_residency;
114 dev->states_usage[entered_state].usage++;
115 } else {
116 dev->last_residency = 0;
117 }
118
119 return entered_state;
120}
121
122/**
95 * cpuidle_idle_call - the main idle loop 123 * cpuidle_idle_call - the main idle loop
96 * 124 *
97 * NOTE: no locks or semaphores should be used here 125 * NOTE: no locks or semaphores should be used here
@@ -113,15 +141,6 @@ int cpuidle_idle_call(void)
113 if (!dev || !dev->enabled) 141 if (!dev || !dev->enabled)
114 return -EBUSY; 142 return -EBUSY;
115 143
116#if 0
117 /* shows regressions, re-enable for 2.6.29 */
118 /*
119 * run any timers that can be run now, at this point
120 * before calculating the idle duration etc.
121 */
122 hrtimer_peek_ahead_timers();
123#endif
124
125 /* ask the governor for the next state */ 144 /* ask the governor for the next state */
126 next_state = cpuidle_curr_governor->select(drv, dev); 145 next_state = cpuidle_curr_governor->select(drv, dev);
127 if (need_resched()) { 146 if (need_resched()) {
@@ -132,23 +151,15 @@ int cpuidle_idle_call(void)
132 trace_power_start_rcuidle(POWER_CSTATE, next_state, dev->cpu); 151 trace_power_start_rcuidle(POWER_CSTATE, next_state, dev->cpu);
133 trace_cpu_idle_rcuidle(next_state, dev->cpu); 152 trace_cpu_idle_rcuidle(next_state, dev->cpu);
134 153
135 entered_state = cpuidle_enter_ops(dev, drv, next_state); 154 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);
136 159
137 trace_power_end_rcuidle(dev->cpu); 160 trace_power_end_rcuidle(dev->cpu);
138 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); 161 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
139 162
140 if (entered_state >= 0) {
141 /* Update cpuidle counters */
142 /* This can be moved to within driver enter routine
143 * but that results in multiple copies of same code.
144 */
145 dev->states_usage[entered_state].time +=
146 (unsigned long long)dev->last_residency;
147 dev->states_usage[entered_state].usage++;
148 } else {
149 dev->last_residency = 0;
150 }
151
152 /* give the governor an opportunity to reflect on the outcome */ 163 /* give the governor an opportunity to reflect on the outcome */
153 if (cpuidle_curr_governor->reflect) 164 if (cpuidle_curr_governor->reflect)
154 cpuidle_curr_governor->reflect(dev, entered_state); 165 cpuidle_curr_governor->reflect(dev, entered_state);
@@ -299,6 +310,9 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
299 int ret, i; 310 int ret, i;
300 struct cpuidle_driver *drv = cpuidle_get_driver(); 311 struct cpuidle_driver *drv = cpuidle_get_driver();
301 312
313 if (!dev)
314 return -EINVAL;
315
302 if (dev->enabled) 316 if (dev->enabled)
303 return 0; 317 return 0;
304 if (!drv || !cpuidle_curr_governor) 318 if (!drv || !cpuidle_curr_governor)
@@ -383,8 +397,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
383 struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); 397 struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
384 struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); 398 struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
385 399
386 if (!dev)
387 return -EINVAL;
388 if (!try_module_get(cpuidle_driver->owner)) 400 if (!try_module_get(cpuidle_driver->owner))
389 return -EINVAL; 401 return -EINVAL;
390 402
@@ -392,13 +404,25 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
392 404
393 per_cpu(cpuidle_devices, dev->cpu) = dev; 405 per_cpu(cpuidle_devices, dev->cpu) = dev;
394 list_add(&dev->device_list, &cpuidle_detected_devices); 406 list_add(&dev->device_list, &cpuidle_detected_devices);
395 if ((ret = cpuidle_add_sysfs(cpu_dev))) { 407 ret = cpuidle_add_sysfs(cpu_dev);
396 module_put(cpuidle_driver->owner); 408 if (ret)
397 return ret; 409 goto err_sysfs;
398 } 410
411 ret = cpuidle_coupled_register_device(dev);
412 if (ret)
413 goto err_coupled;
399 414
400 dev->registered = 1; 415 dev->registered = 1;
401 return 0; 416 return 0;
417
418err_coupled:
419 cpuidle_remove_sysfs(cpu_dev);
420 wait_for_completion(&dev->kobj_unregister);
421err_sysfs:
422 list_del(&dev->device_list);
423 per_cpu(cpuidle_devices, dev->cpu) = NULL;
424 module_put(cpuidle_driver->owner);
425 return ret;
402} 426}
403 427
404/** 428/**
@@ -409,6 +433,9 @@ int cpuidle_register_device(struct cpuidle_device *dev)
409{ 433{
410 int ret; 434 int ret;
411 435
436 if (!dev)
437 return -EINVAL;
438
412 mutex_lock(&cpuidle_lock); 439 mutex_lock(&cpuidle_lock);
413 440
414 if ((ret = __cpuidle_register_device(dev))) { 441 if ((ret = __cpuidle_register_device(dev))) {
@@ -448,6 +475,8 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
448 wait_for_completion(&dev->kobj_unregister); 475 wait_for_completion(&dev->kobj_unregister);
449 per_cpu(cpuidle_devices, dev->cpu) = NULL; 476 per_cpu(cpuidle_devices, dev->cpu) = NULL;
450 477
478 cpuidle_coupled_unregister_device(dev);
479
451 cpuidle_resume_and_unlock(); 480 cpuidle_resume_and_unlock();
452 481
453 module_put(cpuidle_driver->owner); 482 module_put(cpuidle_driver->owner);