瀏覽代碼

cpufreq: Initialize the governor again while restoring policy

When all CPUs of a policy are hot-unplugged, we EXIT the governor but
don't mark policy->governor as NULL. This was done in order to keep last
used governor's information intact in sysfs, while the CPUs are offline.

But we also need to clear policy->governor when restoring the policy.

Because policy->governor still points to the last governor while policy
is restored, following sequence of event happens:
 - cpufreq_init_policy() called while restoring policy
 - find_governor() matches last_governor string for present governors and
   returns last used governor's pointer, say ondemand. policy->governor
   already has the same address, unless the governor was removed in
   between.
 - cpufreq_set_policy() is called with both old/new policies governor set
   as ondemand.
 - Because governors matched, we skip governor initialization and return
   after calling __cpufreq_governor(CPUFREQ_GOV_LIMITS). Because the
   governor wasn't initialized for this policy, it returned -EBUSY.
 - cpufreq_init_policy() exits the policy on this error, but doesn't
   destroy it properly (should be fixed separately).
 - And so we enter a scenario where the policy isn't completely
   initialized but used.

Fix this by setting policy->governor to NULL while restoring the policy.

Reported-and-tested-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
Reported-and-tested-by: "Jon Medhurst (Tixy)" <tixy@linaro.org>
Reported-and-tested-by: Steven Rostedt <rostedt@goodmis.org>
Fixes: 18bf3a124ef8 (cpufreq: Mark policy->governor = NULL for inactive policies)
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Viresh Kumar 10 年之前
父節點
當前提交
35afd02e30
共有 1 個文件被更改,包括 1 次插入0 次删除
  1. 1 0
      drivers/cpufreq/cpufreq.c

+ 1 - 0
drivers/cpufreq/cpufreq.c

@@ -1132,6 +1132,7 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
 
 
 		down_write(&policy->rwsem);
 		down_write(&policy->rwsem);
 		policy->cpu = cpu;
 		policy->cpu = cpu;
+		policy->governor = NULL;
 		up_write(&policy->rwsem);
 		up_write(&policy->rwsem);
 	}
 	}