diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-16 19:56:47 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-16 19:56:47 -0500 |
commit | 9612a461c1e48f75ca1e1f0faf9c928761baae5b (patch) | |
tree | 19b80da3e4cabca51dcbc5a4f7432312ea251351 | |
parent | 4ff913373a77b99cbe3c5df3c76d2622006200d6 (diff) | |
parent | 4955a5412cad83da6e994d939bdb4f7887e4585e (diff) |
Merge branch 'pm-cpuidle'
* pm-cpuidle:
intel_idle: remove superfluous dev->state_count initialization
intel_idle: do C1E promotion disable quirk for hotplugged CPUs
ACPI / cpuidle: remove dev->state_count setting
ACPI / cpuidle: fix max idle state handling with hotplug CPU support
POWERPC: pseries: cpuidle: use the common cpuidle_[un]register() routines
POWERPC: pseries: cpuidle: remove superfluous dev->state_count initialization
ARM: EXYNOS: cpuidle: fix AFTR mode check
-rw-r--r-- | arch/arm/mach-exynos/cpuidle.c | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/processor_idle.c | 59 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 29 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 32 |
4 files changed, 22 insertions, 106 deletions
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index ddbfe8709fe7..8e0eb2ef8c41 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c | |||
@@ -151,8 +151,8 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev, | |||
151 | { | 151 | { |
152 | int new_index = index; | 152 | int new_index = index; |
153 | 153 | ||
154 | /* This mode only can be entered when other core's are offline */ | 154 | /* AFTR can only be entered when cores other than CPU0 are offline */ |
155 | if (num_online_cpus() > 1) | 155 | if (num_online_cpus() > 1 || dev->cpu != 0) |
156 | new_index = drv->safe_state_index; | 156 | new_index = drv->safe_state_index; |
157 | 157 | ||
158 | if (new_index == 0) | 158 | if (new_index == 0) |
@@ -214,10 +214,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) | |||
214 | device = &per_cpu(exynos4_cpuidle_device, cpu_id); | 214 | device = &per_cpu(exynos4_cpuidle_device, cpu_id); |
215 | device->cpu = cpu_id; | 215 | device->cpu = cpu_id; |
216 | 216 | ||
217 | /* Support IDLE only */ | ||
218 | if (cpu_id != 0) | ||
219 | device->state_count = 1; | ||
220 | |||
221 | ret = cpuidle_register_device(device); | 217 | ret = cpuidle_register_device(device); |
222 | if (ret) { | 218 | if (ret) { |
223 | dev_err(&pdev->dev, "failed to register cpuidle device\n"); | 219 | dev_err(&pdev->dev, "failed to register cpuidle device\n"); |
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index a166e38bd683..94134a5aecaa 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c | |||
@@ -28,7 +28,6 @@ struct cpuidle_driver pseries_idle_driver = { | |||
28 | #define MAX_IDLE_STATE_COUNT 2 | 28 | #define MAX_IDLE_STATE_COUNT 2 |
29 | 29 | ||
30 | static int max_idle_state = MAX_IDLE_STATE_COUNT - 1; | 30 | static int max_idle_state = MAX_IDLE_STATE_COUNT - 1; |
31 | static struct cpuidle_device __percpu *pseries_cpuidle_devices; | ||
32 | static struct cpuidle_state *cpuidle_state_table; | 31 | static struct cpuidle_state *cpuidle_state_table; |
33 | 32 | ||
34 | static inline void idle_loop_prolog(unsigned long *in_purr) | 33 | static inline void idle_loop_prolog(unsigned long *in_purr) |
@@ -191,7 +190,7 @@ static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, | |||
191 | { | 190 | { |
192 | int hotcpu = (unsigned long)hcpu; | 191 | int hotcpu = (unsigned long)hcpu; |
193 | struct cpuidle_device *dev = | 192 | struct cpuidle_device *dev = |
194 | per_cpu_ptr(pseries_cpuidle_devices, hotcpu); | 193 | per_cpu_ptr(cpuidle_devices, hotcpu); |
195 | 194 | ||
196 | if (dev && cpuidle_get_driver()) { | 195 | if (dev && cpuidle_get_driver()) { |
197 | switch (action) { | 196 | switch (action) { |
@@ -248,50 +247,6 @@ static int pseries_cpuidle_driver_init(void) | |||
248 | return 0; | 247 | return 0; |
249 | } | 248 | } |
250 | 249 | ||
251 | /* pseries_idle_devices_uninit(void) | ||
252 | * unregister cpuidle devices and de-allocate memory | ||
253 | */ | ||
254 | static void pseries_idle_devices_uninit(void) | ||
255 | { | ||
256 | int i; | ||
257 | struct cpuidle_device *dev; | ||
258 | |||
259 | for_each_possible_cpu(i) { | ||
260 | dev = per_cpu_ptr(pseries_cpuidle_devices, i); | ||
261 | cpuidle_unregister_device(dev); | ||
262 | } | ||
263 | |||
264 | free_percpu(pseries_cpuidle_devices); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | /* pseries_idle_devices_init() | ||
269 | * allocate, initialize and register cpuidle device | ||
270 | */ | ||
271 | static int pseries_idle_devices_init(void) | ||
272 | { | ||
273 | int i; | ||
274 | struct cpuidle_driver *drv = &pseries_idle_driver; | ||
275 | struct cpuidle_device *dev; | ||
276 | |||
277 | pseries_cpuidle_devices = alloc_percpu(struct cpuidle_device); | ||
278 | if (pseries_cpuidle_devices == NULL) | ||
279 | return -ENOMEM; | ||
280 | |||
281 | for_each_possible_cpu(i) { | ||
282 | dev = per_cpu_ptr(pseries_cpuidle_devices, i); | ||
283 | dev->state_count = drv->state_count; | ||
284 | dev->cpu = i; | ||
285 | if (cpuidle_register_device(dev)) { | ||
286 | printk(KERN_DEBUG \ | ||
287 | "cpuidle_register_device %d failed!\n", i); | ||
288 | return -EIO; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | /* | 250 | /* |
296 | * pseries_idle_probe() | 251 | * pseries_idle_probe() |
297 | * Choose state table for shared versus dedicated partition | 252 | * Choose state table for shared versus dedicated partition |
@@ -327,19 +282,12 @@ static int __init pseries_processor_idle_init(void) | |||
327 | return retval; | 282 | return retval; |
328 | 283 | ||
329 | pseries_cpuidle_driver_init(); | 284 | pseries_cpuidle_driver_init(); |
330 | retval = cpuidle_register_driver(&pseries_idle_driver); | 285 | retval = cpuidle_register(&pseries_idle_driver, NULL); |
331 | if (retval) { | 286 | if (retval) { |
332 | printk(KERN_DEBUG "Registration of pseries driver failed.\n"); | 287 | printk(KERN_DEBUG "Registration of pseries driver failed.\n"); |
333 | return retval; | 288 | return retval; |
334 | } | 289 | } |
335 | 290 | ||
336 | retval = pseries_idle_devices_init(); | ||
337 | if (retval) { | ||
338 | pseries_idle_devices_uninit(); | ||
339 | cpuidle_unregister_driver(&pseries_idle_driver); | ||
340 | return retval; | ||
341 | } | ||
342 | |||
343 | register_cpu_notifier(&setup_hotplug_notifier); | 291 | register_cpu_notifier(&setup_hotplug_notifier); |
344 | printk(KERN_DEBUG "pseries_idle_driver registered\n"); | 292 | printk(KERN_DEBUG "pseries_idle_driver registered\n"); |
345 | 293 | ||
@@ -350,8 +298,7 @@ static void __exit pseries_processor_idle_exit(void) | |||
350 | { | 298 | { |
351 | 299 | ||
352 | unregister_cpu_notifier(&setup_hotplug_notifier); | 300 | unregister_cpu_notifier(&setup_hotplug_notifier); |
353 | pseries_idle_devices_uninit(); | 301 | cpuidle_unregister(&pseries_idle_driver); |
354 | cpuidle_unregister_driver(&pseries_idle_driver); | ||
355 | 302 | ||
356 | return; | 303 | return; |
357 | } | 304 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 799644c3888c..1fc455b8ce17 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -783,6 +783,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
783 | if (unlikely(!pr)) | 783 | if (unlikely(!pr)) |
784 | return -EINVAL; | 784 | return -EINVAL; |
785 | 785 | ||
786 | #ifdef CONFIG_HOTPLUG_CPU | ||
787 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
788 | !pr->flags.has_cst && | ||
789 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
790 | return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START); | ||
791 | #endif | ||
792 | |||
786 | if (cx->entry_method == ACPI_CSTATE_FFH) { | 793 | if (cx->entry_method == ACPI_CSTATE_FFH) { |
787 | if (current_set_polling_and_test()) | 794 | if (current_set_polling_and_test()) |
788 | return -EINVAL; | 795 | return -EINVAL; |
@@ -829,6 +836,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
829 | if (unlikely(!pr)) | 836 | if (unlikely(!pr)) |
830 | return -EINVAL; | 837 | return -EINVAL; |
831 | 838 | ||
839 | #ifdef CONFIG_HOTPLUG_CPU | ||
840 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
841 | !pr->flags.has_cst && | ||
842 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
843 | return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START); | ||
844 | #endif | ||
845 | |||
832 | if (!cx->bm_sts_skip && acpi_idle_bm_check()) { | 846 | if (!cx->bm_sts_skip && acpi_idle_bm_check()) { |
833 | if (drv->safe_state_index >= 0) { | 847 | if (drv->safe_state_index >= 0) { |
834 | return drv->states[drv->safe_state_index].enter(dev, | 848 | return drv->states[drv->safe_state_index].enter(dev, |
@@ -930,12 +944,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | |||
930 | if (!cx->valid) | 944 | if (!cx->valid) |
931 | continue; | 945 | continue; |
932 | 946 | ||
933 | #ifdef CONFIG_HOTPLUG_CPU | ||
934 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
935 | !pr->flags.has_cst && | ||
936 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
937 | continue; | ||
938 | #endif | ||
939 | per_cpu(acpi_cstate[count], dev->cpu) = cx; | 947 | per_cpu(acpi_cstate[count], dev->cpu) = cx; |
940 | 948 | ||
941 | count++; | 949 | count++; |
@@ -943,8 +951,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | |||
943 | break; | 951 | break; |
944 | } | 952 | } |
945 | 953 | ||
946 | dev->state_count = count; | ||
947 | |||
948 | if (!count) | 954 | if (!count) |
949 | return -EINVAL; | 955 | return -EINVAL; |
950 | 956 | ||
@@ -985,13 +991,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
985 | if (!cx->valid) | 991 | if (!cx->valid) |
986 | continue; | 992 | continue; |
987 | 993 | ||
988 | #ifdef CONFIG_HOTPLUG_CPU | ||
989 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
990 | !pr->flags.has_cst && | ||
991 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
992 | continue; | ||
993 | #endif | ||
994 | |||
995 | state = &drv->states[count]; | 994 | state = &drv->states[count]; |
996 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); | 995 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); |
997 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); | 996 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 797ed29a36ea..282186e53290 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -644,39 +644,10 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
644 | */ | 644 | */ |
645 | static int intel_idle_cpu_init(int cpu) | 645 | static int intel_idle_cpu_init(int cpu) |
646 | { | 646 | { |
647 | int cstate; | ||
648 | struct cpuidle_device *dev; | 647 | struct cpuidle_device *dev; |
649 | 648 | ||
650 | dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); | 649 | dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); |
651 | 650 | ||
652 | dev->state_count = 1; | ||
653 | |||
654 | for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { | ||
655 | int num_substates, mwait_hint, mwait_cstate, mwait_substate; | ||
656 | |||
657 | if (cpuidle_state_table[cstate].enter == NULL) | ||
658 | break; | ||
659 | |||
660 | if (cstate + 1 > max_cstate) { | ||
661 | printk(PREFIX "max_cstate %d reached\n", max_cstate); | ||
662 | break; | ||
663 | } | ||
664 | |||
665 | mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); | ||
666 | mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); | ||
667 | mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint); | ||
668 | |||
669 | /* does the state exist in CPUID.MWAIT? */ | ||
670 | num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) | ||
671 | & MWAIT_SUBSTATE_MASK; | ||
672 | |||
673 | /* if sub-state in table is not enumerated by CPUID */ | ||
674 | if ((mwait_substate + 1) > num_substates) | ||
675 | continue; | ||
676 | |||
677 | dev->state_count += 1; | ||
678 | } | ||
679 | |||
680 | dev->cpu = cpu; | 651 | dev->cpu = cpu; |
681 | 652 | ||
682 | if (cpuidle_register_device(dev)) { | 653 | if (cpuidle_register_device(dev)) { |
@@ -688,6 +659,9 @@ static int intel_idle_cpu_init(int cpu) | |||
688 | if (icpu->auto_demotion_disable_flags) | 659 | if (icpu->auto_demotion_disable_flags) |
689 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); | 660 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); |
690 | 661 | ||
662 | if (icpu->disable_promotion_to_c1e) | ||
663 | smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1); | ||
664 | |||
691 | return 0; | 665 | return 0; |
692 | } | 666 | } |
693 | 667 | ||