aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2012-01-19 12:18:43 -0500
committerLen Brown <len.brown@intel.com>2012-01-19 21:26:32 -0500
commit99b725084450bbc6f8e1ab20a0df4cc291c342b5 (patch)
tree74d4dd48ff460cc92cf55c19aef8b5c52448e825
parent54d5dcc45af7adbb907072d042bbece4c2b4de6e (diff)
ACPI processor hotplug: Delay acpi_processor_start() call for hotplugged cores
Delay the setting up of features (cpuidle, throttling by calling acpi_processor_start()) to the time when the hotplugged core got onlined the first time and got fully initialized. Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/processor_driver.c72
-rw-r--r--drivers/idle/intel_idle.c2
-rw-r--r--include/acpi/processor.h1
3 files changed, 67 insertions, 8 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index bec55937cf1..2b805d7ef31 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -84,7 +84,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type);
84static void acpi_processor_notify(struct acpi_device *device, u32 event); 84static void acpi_processor_notify(struct acpi_device *device, u32 event);
85static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr); 85static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
86static int acpi_processor_handle_eject(struct acpi_processor *pr); 86static int acpi_processor_handle_eject(struct acpi_processor *pr);
87 87static int acpi_processor_start(struct acpi_processor *pr);
88 88
89static const struct acpi_device_id processor_device_ids[] = { 89static const struct acpi_device_id processor_device_ids[] = {
90 {ACPI_PROCESSOR_OBJECT_HID, 0}, 90 {ACPI_PROCESSOR_OBJECT_HID, 0},
@@ -423,10 +423,29 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
423 struct acpi_processor *pr = per_cpu(processors, cpu); 423 struct acpi_processor *pr = per_cpu(processors, cpu);
424 424
425 if (action == CPU_ONLINE && pr) { 425 if (action == CPU_ONLINE && pr) {
426 acpi_processor_ppc_has_changed(pr, 0); 426 /* CPU got physically hotplugged and onlined the first time:
427 acpi_processor_hotplug(pr); 427 * Initialize missing things
428 acpi_processor_reevaluate_tstate(pr, action); 428 */
429 acpi_processor_tstate_has_changed(pr); 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 "
434 "CPU: %d\n", pr->id);
435 WARN(acpi_processor_start(pr), "Failed to start CPU:"
436 " %d\n", pr->id);
437 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 */
443 } else {
444 acpi_processor_ppc_has_changed(pr, 0);
445 acpi_processor_cst_has_changed(pr);
446 acpi_processor_reevaluate_tstate(pr, action);
447 acpi_processor_tstate_has_changed(pr);
448 }
430 } 449 }
431 if (action == CPU_DEAD && pr) { 450 if (action == CPU_DEAD && pr) {
432 /* invalidate the flag.throttling after one CPU is offline */ 451 /* invalidate the flag.throttling after one CPU is offline */
@@ -440,7 +459,15 @@ static struct notifier_block acpi_cpu_notifier =
440 .notifier_call = acpi_cpu_soft_notify, 459 .notifier_call = acpi_cpu_soft_notify,
441}; 460};
442 461
443static int __cpuinit acpi_processor_start(struct acpi_processor *pr) 462/*
463 * acpi_processor_start() is called by the cpu_hotplug_notifier func:
464 * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the
465 * root cause seem to be that acpi_processor_uninstall_hotplug_notify()
466 * is in the module_exit (__exit) func. Allowing acpi_processor_start()
467 * to not be in __cpuinit section, but being called from __cpuinit funcs
468 * via __ref looks like the right thing to do here.
469 */
470static __ref int acpi_processor_start(struct acpi_processor *pr)
444{ 471{
445 struct acpi_device *device = per_cpu(processor_device_array, pr->id); 472 struct acpi_device *device = per_cpu(processor_device_array, pr->id);
446 int result = 0; 473 int result = 0;
@@ -491,7 +518,12 @@ err_power_exit:
491 return result; 518 return result;
492} 519}
493 520
494 521/*
522 * Do not put anything in here which needs the core to be online.
523 * For example MSR access or setting up things which check for cpuinfo_x86
524 * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
525 * Such things have to be put in and set up above in acpi_processor_start()
526 */
495static int __cpuinit acpi_processor_add(struct acpi_device *device) 527static int __cpuinit acpi_processor_add(struct acpi_device *device)
496{ 528{
497 struct acpi_processor *pr = NULL; 529 struct acpi_processor *pr = NULL;
@@ -546,6 +578,21 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
546 result = -EFAULT; 578 result = -EFAULT;
547 goto err_free_cpumask; 579 goto err_free_cpumask;
548 } 580 }
581
582 /*
583 * Do not start hotplugged CPUs now, but when they
584 * are onlined the first time
585 */
586 if (pr->flags.need_hotplug_init)
587 return 0;
588
589 /*
590 * Do not start hotplugged CPUs now, but when they
591 * are onlined the first time
592 */
593 if (pr->flags.need_hotplug_init)
594 return 0;
595
549 result = acpi_processor_start(pr); 596 result = acpi_processor_start(pr);
550 if (result) 597 if (result)
551 goto err_remove_sysfs; 598 goto err_remove_sysfs;
@@ -751,6 +798,17 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
751 return AE_ERROR; 798 return AE_ERROR;
752 } 799 }
753 800
801 /* CPU got hot-plugged, but cpu_data is not initialized yet
802 * Set flag to delay cpu_idle/throttling initialization
803 * in:
804 * acpi_processor_add()
805 * acpi_processor_get_info()
806 * and do it when the CPU gets online the first time
807 * TBD: Cleanup above functions and try to do this more elegant.
808 */
809 printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
810 pr->flags.need_hotplug_init = 1;
811
754 return AE_OK; 812 return AE_OK;
755} 813}
756 814
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 20bce51c2e8..54ab97bae04 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -527,7 +527,7 @@ int intel_idle_cpu_init(int cpu)
527 527
528 return 0; 528 return 0;
529} 529}
530 530EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
531 531
532static int __init intel_idle_init(void) 532static int __init intel_idle_init(void)
533{ 533{
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 610f6fb1bbc..8cf7e98a2c7 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -195,6 +195,7 @@ struct acpi_processor_flags {
195 u8 has_cst:1; 195 u8 has_cst:1;
196 u8 power_setup_done:1; 196 u8 power_setup_done:1;
197 u8 bm_rld_set:1; 197 u8 bm_rld_set:1;
198 u8 need_hotplug_init:1;
198}; 199};
199 200
200struct acpi_processor { 201struct acpi_processor {