Skip to content

Commit

Permalink
cpufreq: s3c: fix unbalances of cpufreq policy refcount
Browse files Browse the repository at this point in the history
The cpufreq_reboot_notifier_evt() call cpufreq_cpu_get() to get the
cpufreq policy of cpu0, meanwhile, it also increments the kobject
reference count to mark it busy. However, a corresponding call of
cpufreq_cpu_put() is ignored to decrement the kobject reference count
back, which may lead to a potential stuck risk that the cpuhp thread
deadly waits for dropping of kobject refcount when cpufreq policy free.

With this patch, the cpuhp thread can be easily exercised by attempting
to force an unbind of the CPUfreq driver.

Signed-off-by: chenqiwu <chenqiwu@xiaomi.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
  • Loading branch information
chenqiwu authored and Viresh Kumar committed Jan 7, 2020
1 parent 83fe39a commit 8ead819
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
12 changes: 11 additions & 1 deletion drivers/cpufreq/s3c2416-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ static int s3c2416_cpufreq_reboot_notifier_evt(struct notifier_block *this,
{
struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
int ret;
struct cpufreq_policy *policy;

mutex_lock(&cpufreq_lock);

Expand All @@ -318,7 +319,16 @@ static int s3c2416_cpufreq_reboot_notifier_evt(struct notifier_block *this,
*/
if (s3c_freq->is_dvs) {
pr_debug("cpufreq: leave dvs on reboot\n");
ret = cpufreq_driver_target(cpufreq_cpu_get(0), FREQ_SLEEP, 0);

policy = cpufreq_cpu_get(0);
if (!policy) {
pr_debug("cpufreq: get no policy for cpu0\n");
return NOTIFY_BAD;
}

ret = cpufreq_driver_target(policy, FREQ_SLEEP, 0);
cpufreq_cpu_put(policy);

if (ret < 0)
return NOTIFY_BAD;
}
Expand Down
11 changes: 10 additions & 1 deletion drivers/cpufreq/s5pv210-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,17 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int ret;
struct cpufreq_policy *policy;

policy = cpufreq_cpu_get(0);
if (!policy) {
pr_debug("cpufreq: get no policy for cpu0\n");
return NOTIFY_BAD;
}

ret = cpufreq_driver_target(policy, SLEEP_FREQ, 0);
cpufreq_cpu_put(policy);

ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
if (ret < 0)
return NOTIFY_BAD;

Expand Down

0 comments on commit 8ead819

Please sign in to comment.