diff options
-rw-r--r-- | drivers/acpi/processor_driver.c | 7 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 39 | ||||
-rw-r--r-- | drivers/base/power/main.c | 4 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 17 | ||||
-rw-r--r-- | drivers/cpuidle/driver.c | 29 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 5 | ||||
-rw-r--r-- | drivers/cpuidle/sysfs.c | 21 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 41 | ||||
-rw-r--r-- | include/acpi/processor.h | 3 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 19 |
10 files changed, 100 insertions, 85 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0734086537b8..8648b29f6eec 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -427,18 +427,11 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, | |||
427 | * Initialize missing things | 427 | * Initialize missing things |
428 | */ | 428 | */ |
429 | if (pr->flags.need_hotplug_init) { | 429 | if (pr->flags.need_hotplug_init) { |
430 | struct cpuidle_driver *idle_driver = | ||
431 | cpuidle_get_driver(); | ||
432 | |||
433 | printk(KERN_INFO "Will online and init hotplugged " | 430 | printk(KERN_INFO "Will online and init hotplugged " |
434 | "CPU: %d\n", pr->id); | 431 | "CPU: %d\n", pr->id); |
435 | WARN(acpi_processor_start(pr), "Failed to start CPU:" | 432 | WARN(acpi_processor_start(pr), "Failed to start CPU:" |
436 | " %d\n", pr->id); | 433 | " %d\n", pr->id); |
437 | pr->flags.need_hotplug_init = 0; | 434 | pr->flags.need_hotplug_init = 0; |
438 | if (idle_driver && !strcmp(idle_driver->name, | ||
439 | "intel_idle")) { | ||
440 | intel_idle_cpu_init(pr->id); | ||
441 | } | ||
442 | /* Normal CPU soft online event */ | 435 | /* Normal CPU soft online event */ |
443 | } else { | 436 | } else { |
444 | acpi_processor_ppc_has_changed(pr, 0); | 437 | acpi_processor_ppc_has_changed(pr, 0); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 47a8caa89dbe..4cf964803d7a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -221,10 +221,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr, | |||
221 | 221 | ||
222 | #endif | 222 | #endif |
223 | 223 | ||
224 | /* | ||
225 | * Suspend / resume control | ||
226 | */ | ||
227 | static int acpi_idle_suspend; | ||
228 | static u32 saved_bm_rld; | 224 | static u32 saved_bm_rld; |
229 | 225 | ||
230 | static void acpi_idle_bm_rld_save(void) | 226 | static void acpi_idle_bm_rld_save(void) |
@@ -243,21 +239,13 @@ static void acpi_idle_bm_rld_restore(void) | |||
243 | 239 | ||
244 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) | 240 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) |
245 | { | 241 | { |
246 | if (acpi_idle_suspend == 1) | ||
247 | return 0; | ||
248 | |||
249 | acpi_idle_bm_rld_save(); | 242 | acpi_idle_bm_rld_save(); |
250 | acpi_idle_suspend = 1; | ||
251 | return 0; | 243 | return 0; |
252 | } | 244 | } |
253 | 245 | ||
254 | int acpi_processor_resume(struct acpi_device * device) | 246 | int acpi_processor_resume(struct acpi_device * device) |
255 | { | 247 | { |
256 | if (acpi_idle_suspend == 0) | ||
257 | return 0; | ||
258 | |||
259 | acpi_idle_bm_rld_restore(); | 248 | acpi_idle_bm_rld_restore(); |
260 | acpi_idle_suspend = 0; | ||
261 | return 0; | 249 | return 0; |
262 | } | 250 | } |
263 | 251 | ||
@@ -595,7 +583,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
595 | */ | 583 | */ |
596 | cx->valid = 1; | 584 | cx->valid = 1; |
597 | 585 | ||
598 | cx->latency_ticks = cx->latency; | ||
599 | /* | 586 | /* |
600 | * On older chipsets, BM_RLD needs to be set | 587 | * On older chipsets, BM_RLD needs to be set |
601 | * in order for Bus Master activity to wake the | 588 | * in order for Bus Master activity to wake the |
@@ -628,7 +615,6 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
628 | if (!cx->address) | 615 | if (!cx->address) |
629 | break; | 616 | break; |
630 | cx->valid = 1; | 617 | cx->valid = 1; |
631 | cx->latency_ticks = cx->latency; /* Normalize latency */ | ||
632 | break; | 618 | break; |
633 | 619 | ||
634 | case ACPI_STATE_C3: | 620 | case ACPI_STATE_C3: |
@@ -763,11 +749,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
763 | 749 | ||
764 | local_irq_disable(); | 750 | local_irq_disable(); |
765 | 751 | ||
766 | if (acpi_idle_suspend) { | ||
767 | local_irq_enable(); | ||
768 | cpu_relax(); | ||
769 | return -EBUSY; | ||
770 | } | ||
771 | 752 | ||
772 | lapic_timer_state_broadcast(pr, cx, 1); | 753 | lapic_timer_state_broadcast(pr, cx, 1); |
773 | kt1 = ktime_get_real(); | 754 | kt1 = ktime_get_real(); |
@@ -779,7 +760,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
779 | dev->last_residency = (int)idle_time; | 760 | dev->last_residency = (int)idle_time; |
780 | 761 | ||
781 | local_irq_enable(); | 762 | local_irq_enable(); |
782 | cx->usage++; | ||
783 | lapic_timer_state_broadcast(pr, cx, 0); | 763 | lapic_timer_state_broadcast(pr, cx, 0); |
784 | 764 | ||
785 | return index; | 765 | return index; |
@@ -838,11 +818,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
838 | 818 | ||
839 | local_irq_disable(); | 819 | local_irq_disable(); |
840 | 820 | ||
841 | if (acpi_idle_suspend) { | ||
842 | local_irq_enable(); | ||
843 | cpu_relax(); | ||
844 | return -EBUSY; | ||
845 | } | ||
846 | 821 | ||
847 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 822 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
848 | current_thread_info()->status &= ~TS_POLLING; | 823 | current_thread_info()->status &= ~TS_POLLING; |
@@ -887,10 +862,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
887 | if (cx->entry_method != ACPI_CSTATE_FFH) | 862 | if (cx->entry_method != ACPI_CSTATE_FFH) |
888 | current_thread_info()->status |= TS_POLLING; | 863 | current_thread_info()->status |= TS_POLLING; |
889 | 864 | ||
890 | cx->usage++; | ||
891 | |||
892 | lapic_timer_state_broadcast(pr, cx, 0); | 865 | lapic_timer_state_broadcast(pr, cx, 0); |
893 | cx->time += idle_time; | ||
894 | return index; | 866 | return index; |
895 | } | 867 | } |
896 | 868 | ||
@@ -928,8 +900,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
928 | drv, drv->safe_state_index); | 900 | drv, drv->safe_state_index); |
929 | } else { | 901 | } else { |
930 | local_irq_disable(); | 902 | local_irq_disable(); |
931 | if (!acpi_idle_suspend) | 903 | acpi_safe_halt(); |
932 | acpi_safe_halt(); | ||
933 | local_irq_enable(); | 904 | local_irq_enable(); |
934 | return -EBUSY; | 905 | return -EBUSY; |
935 | } | 906 | } |
@@ -937,11 +908,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
937 | 908 | ||
938 | local_irq_disable(); | 909 | local_irq_disable(); |
939 | 910 | ||
940 | if (acpi_idle_suspend) { | ||
941 | local_irq_enable(); | ||
942 | cpu_relax(); | ||
943 | return -EBUSY; | ||
944 | } | ||
945 | 911 | ||
946 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 912 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
947 | current_thread_info()->status &= ~TS_POLLING; | 913 | current_thread_info()->status &= ~TS_POLLING; |
@@ -1014,10 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1014 | if (cx->entry_method != ACPI_CSTATE_FFH) | 980 | if (cx->entry_method != ACPI_CSTATE_FFH) |
1015 | current_thread_info()->status |= TS_POLLING; | 981 | current_thread_info()->status |= TS_POLLING; |
1016 | 982 | ||
1017 | cx->usage++; | ||
1018 | |||
1019 | lapic_timer_state_broadcast(pr, cx, 0); | 983 | lapic_timer_state_broadcast(pr, cx, 0); |
1020 | cx->time += idle_time; | ||
1021 | return index; | 984 | return index; |
1022 | } | 985 | } |
1023 | 986 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 9cb845e49334..63048f79de5f 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/async.h> | 29 | #include <linux/async.h> |
30 | #include <linux/suspend.h> | 30 | #include <linux/suspend.h> |
31 | 31 | #include <linux/cpuidle.h> | |
32 | #include "../base.h" | 32 | #include "../base.h" |
33 | #include "power.h" | 33 | #include "power.h" |
34 | 34 | ||
@@ -467,6 +467,7 @@ static void dpm_resume_noirq(pm_message_t state) | |||
467 | mutex_unlock(&dpm_list_mtx); | 467 | mutex_unlock(&dpm_list_mtx); |
468 | dpm_show_time(starttime, state, "noirq"); | 468 | dpm_show_time(starttime, state, "noirq"); |
469 | resume_device_irqs(); | 469 | resume_device_irqs(); |
470 | cpuidle_resume(); | ||
470 | } | 471 | } |
471 | 472 | ||
472 | /** | 473 | /** |
@@ -867,6 +868,7 @@ static int dpm_suspend_noirq(pm_message_t state) | |||
867 | ktime_t starttime = ktime_get(); | 868 | ktime_t starttime = ktime_get(); |
868 | int error = 0; | 869 | int error = 0; |
869 | 870 | ||
871 | cpuidle_pause(); | ||
870 | suspend_device_irqs(); | 872 | suspend_device_irqs(); |
871 | mutex_lock(&dpm_list_mtx); | 873 | mutex_lock(&dpm_list_mtx); |
872 | while (!list_empty(&dpm_late_early_list)) { | 874 | while (!list_empty(&dpm_late_early_list)) { |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d90519cec880..efa9a2ca30e7 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -201,6 +201,22 @@ void cpuidle_resume_and_unlock(void) | |||
201 | 201 | ||
202 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); | 202 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); |
203 | 203 | ||
204 | /* Currently used in suspend/resume path to suspend cpuidle */ | ||
205 | void cpuidle_pause(void) | ||
206 | { | ||
207 | mutex_lock(&cpuidle_lock); | ||
208 | cpuidle_uninstall_idle_handler(); | ||
209 | mutex_unlock(&cpuidle_lock); | ||
210 | } | ||
211 | |||
212 | /* Currently used in suspend/resume path to resume cpuidle */ | ||
213 | void cpuidle_resume(void) | ||
214 | { | ||
215 | mutex_lock(&cpuidle_lock); | ||
216 | cpuidle_install_idle_handler(); | ||
217 | mutex_unlock(&cpuidle_lock); | ||
218 | } | ||
219 | |||
204 | /** | 220 | /** |
205 | * cpuidle_wrap_enter - performs timekeeping and irqen around enter function | 221 | * cpuidle_wrap_enter - performs timekeeping and irqen around enter function |
206 | * @dev: pointer to a valid cpuidle_device object | 222 | * @dev: pointer to a valid cpuidle_device object |
@@ -265,7 +281,6 @@ static void poll_idle_init(struct cpuidle_driver *drv) | |||
265 | state->power_usage = -1; | 281 | state->power_usage = -1; |
266 | state->flags = 0; | 282 | state->flags = 0; |
267 | state->enter = poll_idle; | 283 | state->enter = poll_idle; |
268 | state->disable = 0; | ||
269 | } | 284 | } |
270 | #else | 285 | #else |
271 | static void poll_idle_init(struct cpuidle_driver *drv) {} | 286 | static void poll_idle_init(struct cpuidle_driver *drv) {} |
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 40cd3f3024df..58bf3b1ac9c4 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | static struct cpuidle_driver *cpuidle_curr_driver; | 17 | static struct cpuidle_driver *cpuidle_curr_driver; |
18 | DEFINE_SPINLOCK(cpuidle_driver_lock); | 18 | DEFINE_SPINLOCK(cpuidle_driver_lock); |
19 | int cpuidle_driver_refcount; | ||
19 | 20 | ||
20 | static void __cpuidle_register_driver(struct cpuidle_driver *drv) | 21 | static void __cpuidle_register_driver(struct cpuidle_driver *drv) |
21 | { | 22 | { |
@@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv) | |||
89 | } | 90 | } |
90 | 91 | ||
91 | spin_lock(&cpuidle_driver_lock); | 92 | spin_lock(&cpuidle_driver_lock); |
92 | cpuidle_curr_driver = NULL; | 93 | |
94 | if (!WARN_ON(cpuidle_driver_refcount > 0)) | ||
95 | cpuidle_curr_driver = NULL; | ||
96 | |||
93 | spin_unlock(&cpuidle_driver_lock); | 97 | spin_unlock(&cpuidle_driver_lock); |
94 | } | 98 | } |
95 | 99 | ||
96 | EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); | 100 | EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); |
101 | |||
102 | struct cpuidle_driver *cpuidle_driver_ref(void) | ||
103 | { | ||
104 | struct cpuidle_driver *drv; | ||
105 | |||
106 | spin_lock(&cpuidle_driver_lock); | ||
107 | |||
108 | drv = cpuidle_curr_driver; | ||
109 | cpuidle_driver_refcount++; | ||
110 | |||
111 | spin_unlock(&cpuidle_driver_lock); | ||
112 | return drv; | ||
113 | } | ||
114 | |||
115 | void cpuidle_driver_unref(void) | ||
116 | { | ||
117 | spin_lock(&cpuidle_driver_lock); | ||
118 | |||
119 | if (!WARN_ON(cpuidle_driver_refcount <= 0)) | ||
120 | cpuidle_driver_refcount--; | ||
121 | |||
122 | spin_unlock(&cpuidle_driver_lock); | ||
123 | } | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 06335756ea14..8391d93f57d5 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -281,7 +281,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
281 | * unless the timer is happening really really soon. | 281 | * unless the timer is happening really really soon. |
282 | */ | 282 | */ |
283 | if (data->expected_us > 5 && | 283 | if (data->expected_us > 5 && |
284 | drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) | 284 | dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) |
285 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 285 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
286 | 286 | ||
287 | /* | 287 | /* |
@@ -290,8 +290,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
290 | */ | 290 | */ |
291 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 291 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
292 | struct cpuidle_state *s = &drv->states[i]; | 292 | struct cpuidle_state *s = &drv->states[i]; |
293 | struct cpuidle_state_usage *su = &dev->states_usage[i]; | ||
293 | 294 | ||
294 | if (s->disable) | 295 | if (su->disable) |
295 | continue; | 296 | continue; |
296 | if (s->target_residency > data->predicted_us) | 297 | if (s->target_residency > data->predicted_us) |
297 | continue; | 298 | continue; |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 88032b4dc6d2..5f809e337b89 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -217,7 +217,8 @@ struct cpuidle_state_attr { | |||
217 | struct attribute attr; | 217 | struct attribute attr; |
218 | ssize_t (*show)(struct cpuidle_state *, \ | 218 | ssize_t (*show)(struct cpuidle_state *, \ |
219 | struct cpuidle_state_usage *, char *); | 219 | struct cpuidle_state_usage *, char *); |
220 | ssize_t (*store)(struct cpuidle_state *, const char *, size_t); | 220 | ssize_t (*store)(struct cpuidle_state *, \ |
221 | struct cpuidle_state_usage *, const char *, size_t); | ||
221 | }; | 222 | }; |
222 | 223 | ||
223 | #define define_one_state_ro(_name, show) \ | 224 | #define define_one_state_ro(_name, show) \ |
@@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ | |||
233 | return sprintf(buf, "%u\n", state->_name);\ | 234 | return sprintf(buf, "%u\n", state->_name);\ |
234 | } | 235 | } |
235 | 236 | ||
236 | #define define_store_state_function(_name) \ | 237 | #define define_store_state_ull_function(_name) \ |
237 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ | 238 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ |
239 | struct cpuidle_state_usage *state_usage, \ | ||
238 | const char *buf, size_t size) \ | 240 | const char *buf, size_t size) \ |
239 | { \ | 241 | { \ |
240 | long value; \ | 242 | unsigned long long value; \ |
241 | int err; \ | 243 | int err; \ |
242 | if (!capable(CAP_SYS_ADMIN)) \ | 244 | if (!capable(CAP_SYS_ADMIN)) \ |
243 | return -EPERM; \ | 245 | return -EPERM; \ |
244 | err = kstrtol(buf, 0, &value); \ | 246 | err = kstrtoull(buf, 0, &value); \ |
245 | if (err) \ | 247 | if (err) \ |
246 | return err; \ | 248 | return err; \ |
247 | if (value) \ | 249 | if (value) \ |
248 | state->disable = 1; \ | 250 | state_usage->_name = 1; \ |
249 | else \ | 251 | else \ |
250 | state->disable = 0; \ | 252 | state_usage->_name = 0; \ |
251 | return size; \ | 253 | return size; \ |
252 | } | 254 | } |
253 | 255 | ||
@@ -273,8 +275,8 @@ define_show_state_ull_function(usage) | |||
273 | define_show_state_ull_function(time) | 275 | define_show_state_ull_function(time) |
274 | define_show_state_str_function(name) | 276 | define_show_state_str_function(name) |
275 | define_show_state_str_function(desc) | 277 | define_show_state_str_function(desc) |
276 | define_show_state_function(disable) | 278 | define_show_state_ull_function(disable) |
277 | define_store_state_function(disable) | 279 | define_store_state_ull_function(disable) |
278 | 280 | ||
279 | define_one_state_ro(name, show_state_name); | 281 | define_one_state_ro(name, show_state_name); |
280 | define_one_state_ro(desc, show_state_desc); | 282 | define_one_state_ro(desc, show_state_desc); |
@@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, | |||
318 | { | 320 | { |
319 | int ret = -EIO; | 321 | int ret = -EIO; |
320 | struct cpuidle_state *state = kobj_to_state(kobj); | 322 | struct cpuidle_state *state = kobj_to_state(kobj); |
323 | struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); | ||
321 | struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); | 324 | struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); |
322 | 325 | ||
323 | if (cattr->store) | 326 | if (cattr->store) |
324 | ret = cattr->store(state, buf, size); | 327 | ret = cattr->store(state, state_usage, buf, size); |
325 | 328 | ||
326 | return ret; | 329 | return ret; |
327 | } | 330 | } |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index d0f59c3f87ef..fe95d5464a02 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -96,6 +96,7 @@ static const struct idle_cpu *icpu; | |||
96 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; | 96 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
97 | static int intel_idle(struct cpuidle_device *dev, | 97 | static int intel_idle(struct cpuidle_device *dev, |
98 | struct cpuidle_driver *drv, int index); | 98 | struct cpuidle_driver *drv, int index); |
99 | static int intel_idle_cpu_init(int cpu); | ||
99 | 100 | ||
100 | static struct cpuidle_state *cpuidle_state_table; | 101 | static struct cpuidle_state *cpuidle_state_table; |
101 | 102 | ||
@@ -302,22 +303,35 @@ static void __setup_broadcast_timer(void *arg) | |||
302 | clockevents_notify(reason, &cpu); | 303 | clockevents_notify(reason, &cpu); |
303 | } | 304 | } |
304 | 305 | ||
305 | static int setup_broadcast_cpuhp_notify(struct notifier_block *n, | 306 | static int cpu_hotplug_notify(struct notifier_block *n, |
306 | unsigned long action, void *hcpu) | 307 | unsigned long action, void *hcpu) |
307 | { | 308 | { |
308 | int hotcpu = (unsigned long)hcpu; | 309 | int hotcpu = (unsigned long)hcpu; |
310 | struct cpuidle_device *dev; | ||
309 | 311 | ||
310 | switch (action & 0xf) { | 312 | switch (action & 0xf) { |
311 | case CPU_ONLINE: | 313 | case CPU_ONLINE: |
312 | smp_call_function_single(hotcpu, __setup_broadcast_timer, | 314 | |
313 | (void *)true, 1); | 315 | if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) |
316 | smp_call_function_single(hotcpu, __setup_broadcast_timer, | ||
317 | (void *)true, 1); | ||
318 | |||
319 | /* | ||
320 | * Some systems can hotplug a cpu at runtime after | ||
321 | * the kernel has booted, we have to initialize the | ||
322 | * driver in this case | ||
323 | */ | ||
324 | dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu); | ||
325 | if (!dev->registered) | ||
326 | intel_idle_cpu_init(hotcpu); | ||
327 | |||
314 | break; | 328 | break; |
315 | } | 329 | } |
316 | return NOTIFY_OK; | 330 | return NOTIFY_OK; |
317 | } | 331 | } |
318 | 332 | ||
319 | static struct notifier_block setup_broadcast_notifier = { | 333 | static struct notifier_block cpu_hotplug_notifier = { |
320 | .notifier_call = setup_broadcast_cpuhp_notify, | 334 | .notifier_call = cpu_hotplug_notify, |
321 | }; | 335 | }; |
322 | 336 | ||
323 | static void auto_demotion_disable(void *dummy) | 337 | static void auto_demotion_disable(void *dummy) |
@@ -405,10 +419,10 @@ static int intel_idle_probe(void) | |||
405 | 419 | ||
406 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | 420 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
407 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; | 421 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; |
408 | else { | 422 | else |
409 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); | 423 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); |
410 | register_cpu_notifier(&setup_broadcast_notifier); | 424 | |
411 | } | 425 | register_cpu_notifier(&cpu_hotplug_notifier); |
412 | 426 | ||
413 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION | 427 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION |
414 | " model 0x%X\n", boot_cpu_data.x86_model); | 428 | " model 0x%X\n", boot_cpu_data.x86_model); |
@@ -494,7 +508,7 @@ static int intel_idle_cpuidle_driver_init(void) | |||
494 | * allocate, initialize, register cpuidle_devices | 508 | * allocate, initialize, register cpuidle_devices |
495 | * @cpu: cpu/core to initialize | 509 | * @cpu: cpu/core to initialize |
496 | */ | 510 | */ |
497 | int intel_idle_cpu_init(int cpu) | 511 | static int intel_idle_cpu_init(int cpu) |
498 | { | 512 | { |
499 | int cstate; | 513 | int cstate; |
500 | struct cpuidle_device *dev; | 514 | struct cpuidle_device *dev; |
@@ -539,7 +553,6 @@ int intel_idle_cpu_init(int cpu) | |||
539 | 553 | ||
540 | return 0; | 554 | return 0; |
541 | } | 555 | } |
542 | EXPORT_SYMBOL_GPL(intel_idle_cpu_init); | ||
543 | 556 | ||
544 | static int __init intel_idle_init(void) | 557 | static int __init intel_idle_init(void) |
545 | { | 558 | { |
@@ -581,10 +594,10 @@ static void __exit intel_idle_exit(void) | |||
581 | intel_idle_cpuidle_devices_uninit(); | 594 | intel_idle_cpuidle_devices_uninit(); |
582 | cpuidle_unregister_driver(&intel_idle_driver); | 595 | cpuidle_unregister_driver(&intel_idle_driver); |
583 | 596 | ||
584 | if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) { | 597 | |
598 | if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) | ||
585 | on_each_cpu(__setup_broadcast_timer, (void *)false, 1); | 599 | on_each_cpu(__setup_broadcast_timer, (void *)false, 1); |
586 | unregister_cpu_notifier(&setup_broadcast_notifier); | 600 | unregister_cpu_notifier(&cpu_hotplug_notifier); |
587 | } | ||
588 | 601 | ||
589 | return; | 602 | return; |
590 | } | 603 | } |
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 9d650476d5dc..c72a80160245 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
@@ -59,10 +59,7 @@ struct acpi_processor_cx { | |||
59 | u8 entry_method; | 59 | u8 entry_method; |
60 | u8 index; | 60 | u8 index; |
61 | u32 latency; | 61 | u32 latency; |
62 | u32 latency_ticks; | ||
63 | u32 power; | 62 | u32 power; |
64 | u32 usage; | ||
65 | u64 time; | ||
66 | u8 bm_sts_skip; | 63 | u8 bm_sts_skip; |
67 | char desc[ACPI_CX_DESC_LEN]; | 64 | char desc[ACPI_CX_DESC_LEN]; |
68 | }; | 65 | }; |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e03..ca6cdf55eb18 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -34,6 +34,7 @@ struct cpuidle_driver; | |||
34 | struct cpuidle_state_usage { | 34 | struct cpuidle_state_usage { |
35 | void *driver_data; | 35 | void *driver_data; |
36 | 36 | ||
37 | unsigned long long disable; | ||
37 | unsigned long long usage; | 38 | unsigned long long usage; |
38 | unsigned long long time; /* in US */ | 39 | unsigned long long time; /* in US */ |
39 | }; | 40 | }; |
@@ -46,7 +47,6 @@ struct cpuidle_state { | |||
46 | unsigned int exit_latency; /* in US */ | 47 | unsigned int exit_latency; /* in US */ |
47 | int power_usage; /* in mW */ | 48 | int power_usage; /* in mW */ |
48 | unsigned int target_residency; /* in US */ | 49 | unsigned int target_residency; /* in US */ |
49 | unsigned int disable; | ||
50 | 50 | ||
51 | int (*enter) (struct cpuidle_device *dev, | 51 | int (*enter) (struct cpuidle_device *dev, |
52 | struct cpuidle_driver *drv, | 52 | struct cpuidle_driver *drv, |
@@ -136,13 +136,17 @@ struct cpuidle_driver { | |||
136 | extern void disable_cpuidle(void); | 136 | extern void disable_cpuidle(void); |
137 | extern int cpuidle_idle_call(void); | 137 | extern int cpuidle_idle_call(void); |
138 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); | 138 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); |
139 | struct cpuidle_driver *cpuidle_get_driver(void); | 139 | extern struct cpuidle_driver *cpuidle_get_driver(void); |
140 | extern struct cpuidle_driver *cpuidle_driver_ref(void); | ||
141 | extern void cpuidle_driver_unref(void); | ||
140 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); | 142 | extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); |
141 | extern int cpuidle_register_device(struct cpuidle_device *dev); | 143 | extern int cpuidle_register_device(struct cpuidle_device *dev); |
142 | extern void cpuidle_unregister_device(struct cpuidle_device *dev); | 144 | extern void cpuidle_unregister_device(struct cpuidle_device *dev); |
143 | 145 | ||
144 | extern void cpuidle_pause_and_lock(void); | 146 | extern void cpuidle_pause_and_lock(void); |
145 | extern void cpuidle_resume_and_unlock(void); | 147 | extern void cpuidle_resume_and_unlock(void); |
148 | extern void cpuidle_pause(void); | ||
149 | extern void cpuidle_resume(void); | ||
146 | extern int cpuidle_enable_device(struct cpuidle_device *dev); | 150 | extern int cpuidle_enable_device(struct cpuidle_device *dev); |
147 | extern void cpuidle_disable_device(struct cpuidle_device *dev); | 151 | extern void cpuidle_disable_device(struct cpuidle_device *dev); |
148 | extern int cpuidle_wrap_enter(struct cpuidle_device *dev, | 152 | extern int cpuidle_wrap_enter(struct cpuidle_device *dev, |
@@ -157,6 +161,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; } | |||
157 | static inline int cpuidle_register_driver(struct cpuidle_driver *drv) | 161 | static inline int cpuidle_register_driver(struct cpuidle_driver *drv) |
158 | {return -ENODEV; } | 162 | {return -ENODEV; } |
159 | static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } | 163 | static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } |
164 | static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; } | ||
165 | static inline void cpuidle_driver_unref(void) {} | ||
160 | static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } | 166 | static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } |
161 | static inline int cpuidle_register_device(struct cpuidle_device *dev) | 167 | static inline int cpuidle_register_device(struct cpuidle_device *dev) |
162 | {return -ENODEV; } | 168 | {return -ENODEV; } |
@@ -164,6 +170,8 @@ static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } | |||
164 | 170 | ||
165 | static inline void cpuidle_pause_and_lock(void) { } | 171 | static inline void cpuidle_pause_and_lock(void) { } |
166 | static inline void cpuidle_resume_and_unlock(void) { } | 172 | static inline void cpuidle_resume_and_unlock(void) { } |
173 | static inline void cpuidle_pause(void) { } | ||
174 | static inline void cpuidle_resume(void) { } | ||
167 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) | 175 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) |
168 | {return -ENODEV; } | 176 | {return -ENODEV; } |
169 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } | 177 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } |
@@ -202,14 +210,7 @@ struct cpuidle_governor { | |||
202 | extern int cpuidle_register_governor(struct cpuidle_governor *gov); | 210 | extern int cpuidle_register_governor(struct cpuidle_governor *gov); |
203 | extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); | 211 | extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); |
204 | 212 | ||
205 | #ifdef CONFIG_INTEL_IDLE | ||
206 | extern int intel_idle_cpu_init(int cpu); | ||
207 | #else | 213 | #else |
208 | static inline int intel_idle_cpu_init(int cpu) { return -1; } | ||
209 | #endif | ||
210 | |||
211 | #else | ||
212 | static inline int intel_idle_cpu_init(int cpu) { return -1; } | ||
213 | 214 | ||
214 | static inline int cpuidle_register_governor(struct cpuidle_governor *gov) | 215 | static inline int cpuidle_register_governor(struct cpuidle_governor *gov) |
215 | {return 0;} | 216 | {return 0;} |