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

Commit fdd320da authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

cpufreq: Lock CPU online/offline in cpufreq_register_driver()



To protect against races with concurrent CPU online/offline, call
get_online_cpus() before registering a cpufreq driver.

Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 194d99c7
Loading
Loading
Loading
Loading
+10 −3
Original line number Original line Diff line number Diff line
@@ -2471,10 +2471,14 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)


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


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

	write_lock_irqsave(&cpufreq_driver_lock, flags);
	write_lock_irqsave(&cpufreq_driver_lock, flags);
	if (cpufreq_driver) {
	if (cpufreq_driver) {
		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
		return -EEXIST;
		ret = -EEXIST;
		goto out;
	}
	}
	cpufreq_driver = driver_data;
	cpufreq_driver = driver_data;
	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -2513,7 +2517,10 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
	register_hotcpu_notifier(&cpufreq_cpu_notifier);
	register_hotcpu_notifier(&cpufreq_cpu_notifier);
	pr_debug("driver %s up and running\n", driver_data->name);
	pr_debug("driver %s up and running\n", driver_data->name);


	return 0;
out:
	put_online_cpus();
	return ret;

err_if_unreg:
err_if_unreg:
	subsys_interface_unregister(&cpufreq_interface);
	subsys_interface_unregister(&cpufreq_interface);
err_boost_unreg:
err_boost_unreg:
@@ -2523,7 +2530,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
	write_lock_irqsave(&cpufreq_driver_lock, flags);
	write_lock_irqsave(&cpufreq_driver_lock, flags);
	cpufreq_driver = NULL;
	cpufreq_driver = NULL;
	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
	return ret;
	goto out;
}
}
EXPORT_SYMBOL_GPL(cpufreq_register_driver);
EXPORT_SYMBOL_GPL(cpufreq_register_driver);