Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 852d8cb1 authored by Deepthi Dharwar's avatar Deepthi Dharwar Committed by Benjamin Herrenschmidt
Browse files

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: default avatarDeepthi Dharwar <deepthi@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 8bf8385b
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -197,13 +197,25 @@ static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
	struct cpuidle_device *dev =
			per_cpu_ptr(pseries_cpuidle_devices, hotcpu);

	switch (action & 0xf) {
	case CPU_ONLINE:
	if (dev && cpuidle_get_driver()) {
			cpuidle_disable_device(dev);
		switch (action) {
		case CPU_ONLINE:
		case CPU_ONLINE_FROZEN:
			cpuidle_pause_and_lock();
			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;
		}
	}
	return NOTIFY_OK;
}
@@ -345,6 +357,7 @@ static int __init pseries_processor_idle_init(void)
static void __exit pseries_processor_idle_exit(void)
{

	unregister_cpu_notifier(&setup_hotplug_notifier);
	pseries_idle_devices_uninit();
	cpuidle_unregister_driver(&pseries_idle_driver);