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

Commit d36dd773 authored by Rohit Gupta's avatar Rohit Gupta
Browse files

cpufreq: Register for hotplug notifier before locking hotplug



If a CPU hotplug operation occurs in parallel while a driver is
registering with the cpufreq framework it can lead to the following
deadlock scenario:
Thread A (cpufreq_register_driver())	Thread B (cpu_down())
get_online_cpus()
	|
atomic_inc(&cpu_hotplug.refcount)
					     cpu_down()
						|
				     mutex_lock(&cpu_add_remove_lock)
						|
				     cpu_hotplug_begin() waits on
				     cpu_hotplug.refcount to reset
register_cpu_notifier()
	|
mutex_lock(&cpu_add_remove_lock)

This happens because the registration for hotplug notifiers happens
inside the hotplug locked section.
This change moves hotplug registration call before get_online_cpus()
to avoid the deadlock.

Change-Id: Ia59a3e2710133d3b3608e49938e746e58af5a6d4
Signed-off-by: default avatarRohit Gupta <rohgup@codeaurora.org>
parent a80e267a
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2269,6 +2269,9 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
{
	unsigned int cpu = (unsigned long)hcpu;

	if (!cpufreq_driver)
		return NOTIFY_OK;

	switch (action & ~CPU_TASKS_FROZEN) {
	case CPU_ONLINE:
		cpufreq_online(cpu);
@@ -2435,6 +2438,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)

	pr_debug("trying to register driver %s\n", driver_data->name);

	/* Register for hotplug notifers before blocking hotplug. */
	register_hotcpu_notifier(&cpufreq_cpu_notifier);

	/* Protect against concurrent CPU online/offline. */
	get_online_cpus();

@@ -2466,7 +2472,6 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
		goto err_if_unreg;
	}

	register_hotcpu_notifier(&cpufreq_cpu_notifier);
	pr_info("driver %s up and running\n", driver_data->name);

out: