summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2019-11-14 09:06:17 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-31 12:37:40 +0100
commit7c31408136db6c826911f4a214868048f30839b5 (patch)
treeb193ebf764516ef36382d839b066c9951aaffc75
parent3b524ed1fa05d4e2fef31b47da5abc053cadebd2 (diff)
downloadlinux-stable-7c31408136db6c826911f4a214868048f30839b5.tar.gz
linux-stable-7c31408136db6c826911f4a214868048f30839b5.tar.bz2
linux-stable-7c31408136db6c826911f4a214868048f30839b5.zip
cpufreq: Register drivers only after CPU devices have been registered
[ Upstream commit 46770be0cf94149ca48be87719bda1d951066644 ] The cpufreq core heavily depends on the availability of the struct device for CPUs and if they aren't available at the time cpufreq driver is registered, we will never succeed in making cpufreq work. This happens due to following sequence of events: - cpufreq_register_driver() - subsys_interface_register() - return 0; //successful registration of driver ... at a later point of time - register_cpu(); - device_register(); - bus_probe_device(); - sif->add_dev(); - cpufreq_add_dev(); - get_cpu_device(); //FAILS - per_cpu(cpu_sys_devices, num) = &cpu->dev; //used by get_cpu_device() - return 0; //CPU registered successfully Because the per-cpu variable cpu_sys_devices is set only after the CPU device is regsitered, cpufreq will never be able to get it when cpufreq_add_dev() is called. This patch avoids this failure by making sure device structure of at least CPU0 is available when the cpufreq driver is registered, else return -EPROBE_DEFER. Reported-by: Bjorn Andersson <bjorn.andersson@linaro.org> Co-developed-by: Amit Kucheria <amit.kucheria@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Amit Kucheria <amit.kucheria@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/cpufreq/cpufreq.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 480e8c13567c..c798a1233e6a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2475,6 +2475,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
if (cpufreq_disabled())
return -ENODEV;
+ /*
+ * The cpufreq core depends heavily on the availability of device
+ * structure, make sure they are available before proceeding further.
+ */
+ if (!get_cpu_device(0))
+ return -EPROBE_DEFER;
+
if (!driver_data || !driver_data->verify || !driver_data->init ||
!(driver_data->setpolicy || driver_data->target_index ||
driver_data->target) ||