| From 64737b4bb33c9197e9fc0f41332e75743aa3d27b Mon Sep 17 00:00:00 2001 |
| From: Viresh Kumar <viresh.kumar@linaro.org> |
| Date: Thu, 14 Nov 2019 09:06:17 +0530 |
| Subject: [PATCH] cpufreq: Register drivers only after CPU devices have been |
| registered |
| |
| commit 46770be0cf94149ca48be87719bda1d951066644 upstream. |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c |
| index 21f3b861fb8c..0c888531474f 100644 |
| --- a/drivers/cpufreq/cpufreq.c |
| +++ b/drivers/cpufreq/cpufreq.c |
| @@ -2574,6 +2574,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) || |
| -- |
| 2.7.4 |
| |