cpufreq: Initialize the governor again while restoring policy
authorViresh Kumar <viresh.kumar@linaro.org>
Thu, 9 Jul 2015 23:36:27 +0000 (01:36 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 9 Jul 2015 23:36:27 +0000 (01:36 +0200)
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>
drivers/cpufreq/cpufreq.c

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