powerpc/cpuidle: Fixes for pseries_idle hotplug notifier
Currently the call to pseries_notify_cpuidle_add_cpu(), that takes action on the cpuidle front when a cpu is added/removed is being made from smp_xics_setup_cpu(). This caused lockdep issues as reported https://lkml.org/lkml/2012/5/17/2 On addition of each cpu, resources were cleared and re-allocated each time, all in critical section as part of start_secondary() call were interrupts are disabled. To resolve this issue, the pseries_notify_cpuidle_add_cpu() call is is being replaced by a hotplug notifier which would prevent cpuidle resources from being released and allocated each time cpu is onlined in the critical code path. It was fixed in https://lkml.org/lkml/2012/5/18/174. Also it is essential to call cpuidle_enable/disable_device between cpuidle_pause_and_lock() and cpuidle_resume_and_unlock() when used externally to avoid race conditions. Add support for CPU_ONLINE_FROZEN and CPU_DEAD_FROZEN as part of hotplug notify event for pseries_idle and unregister hotplug notifier while exiting out. The above mentioned issues are fixed as part of this patch. Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
8bf8385b9c
commit
852d8cb1ff
1 changed files with 18 additions and 5 deletions
|
@ -197,13 +197,25 @@ static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
|
||||||
struct cpuidle_device *dev =
|
struct cpuidle_device *dev =
|
||||||
per_cpu_ptr(pseries_cpuidle_devices, hotcpu);
|
per_cpu_ptr(pseries_cpuidle_devices, hotcpu);
|
||||||
|
|
||||||
switch (action & 0xf) {
|
if (dev && cpuidle_get_driver()) {
|
||||||
case CPU_ONLINE:
|
switch (action) {
|
||||||
if (dev && cpuidle_get_driver()) {
|
case CPU_ONLINE:
|
||||||
cpuidle_disable_device(dev);
|
case CPU_ONLINE_FROZEN:
|
||||||
|
cpuidle_pause_and_lock();
|
||||||
cpuidle_enable_device(dev);
|
cpuidle_enable_device(dev);
|
||||||
|
cpuidle_resume_and_unlock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU_DEAD:
|
||||||
|
case CPU_DEAD_FROZEN:
|
||||||
|
cpuidle_pause_and_lock();
|
||||||
|
cpuidle_disable_device(dev);
|
||||||
|
cpuidle_resume_and_unlock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
@ -345,6 +357,7 @@ static int __init pseries_processor_idle_init(void)
|
||||||
static void __exit pseries_processor_idle_exit(void)
|
static void __exit pseries_processor_idle_exit(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
unregister_cpu_notifier(&setup_hotplug_notifier);
|
||||||
pseries_idle_devices_uninit();
|
pseries_idle_devices_uninit();
|
||||||
cpuidle_unregister_driver(&pseries_idle_driver);
|
cpuidle_unregister_driver(&pseries_idle_driver);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue