| From 2c1b5a84669d2477d8fffe9136e86a2cff591729 Mon Sep 17 00:00:00 2001 |
| From: Xiongfeng Wang <wangxiongfeng2@huawei.com> |
| Date: Mon, 29 Nov 2021 16:02:48 +0800 |
| Subject: cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink() |
| |
| From: Xiongfeng Wang <wangxiongfeng2@huawei.com> |
| |
| commit 2c1b5a84669d2477d8fffe9136e86a2cff591729 upstream. |
| |
| When I hot added a CPU, I found 'cpufreq' directory was not created |
| below /sys/devices/system/cpu/cpuX/. |
| |
| It is because get_cpu_device() failed in add_cpu_dev_symlink(). |
| |
| cpufreq_add_dev() is the .add_dev callback of a CPU subsys interface. |
| It will be called when the CPU device registered into the system. |
| The call chain is as follows: |
| |
| register_cpu() |
| ->device_register() |
| ->device_add() |
| ->bus_probe_device() |
| ->cpufreq_add_dev() |
| |
| But only after the CPU device has been registered, we can get the |
| CPU device by get_cpu_device(), otherwise it will return NULL. |
| |
| Since we already have the CPU device in cpufreq_add_dev(), pass |
| it to add_cpu_dev_symlink(). |
| |
| I noticed that the 'kobj' of the CPU device has been added into |
| the system before cpufreq_add_dev(). |
| |
| Fixes: 2f0ba790df51 ("cpufreq: Fix creation of symbolic links to policy directories") |
| Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> |
| Acked-by: Viresh Kumar <viresh.kumar@linaro.org> |
| Cc: All applicable <stable@vger.kernel.org> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/cpufreq/cpufreq.c | 9 ++++----- |
| 1 file changed, 4 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/cpufreq/cpufreq.c |
| +++ b/drivers/cpufreq/cpufreq.c |
| @@ -1004,10 +1004,9 @@ static struct kobj_type ktype_cpufreq = |
| .release = cpufreq_sysfs_release, |
| }; |
| |
| -static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu) |
| +static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu, |
| + struct device *dev) |
| { |
| - struct device *dev = get_cpu_device(cpu); |
| - |
| if (unlikely(!dev)) |
| return; |
| |
| @@ -1391,7 +1390,7 @@ static int cpufreq_online(unsigned int c |
| if (new_policy) { |
| for_each_cpu(j, policy->related_cpus) { |
| per_cpu(cpufreq_cpu_data, j) = policy; |
| - add_cpu_dev_symlink(policy, j); |
| + add_cpu_dev_symlink(policy, j, get_cpu_device(j)); |
| } |
| |
| policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), |
| @@ -1553,7 +1552,7 @@ static int cpufreq_add_dev(struct device |
| /* Create sysfs link on CPU registration */ |
| policy = per_cpu(cpufreq_cpu_data, cpu); |
| if (policy) |
| - add_cpu_dev_symlink(policy, cpu); |
| + add_cpu_dev_symlink(policy, cpu, dev); |
| |
| return 0; |
| } |