Commit 084f3493 authored by Thomas Renninger's avatar Thomas Renninger Committed by Dave Jones

[CPUFREQ] Restore previously used governor on a hot-replugged CPU

Negative side effect: needs NR_CPUs pointer array of memory in
CONFIG_HOTPLUG_CPU case.

Still needs userspace track keeping and rewriting of governors if governors
change while a CPU is not active (always the governor at CPU remove time is
restored).

Move of policy->user_policy.governor assignment is just a minor cleanup.
http://bugzilla.kernel.org/show_bug.cgi?id=8671Signed-off-by: default avatarThomas Renninger <trenn@suse.de>
Signed-off-by: default avatarMattia Dongili <malattia@linux.it>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarDave Jones <davej@redhat.com>
parent 91973de7
...@@ -39,6 +39,10 @@ ...@@ -39,6 +39,10 @@
*/ */
static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_driver *cpufreq_driver;
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */
static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
#endif
static DEFINE_SPINLOCK(cpufreq_driver_lock); static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* /*
...@@ -770,9 +774,17 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -770,9 +774,17 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
} }
policy->user_policy.min = policy->cpuinfo.min_freq; policy->user_policy.min = policy->cpuinfo.min_freq;
policy->user_policy.max = policy->cpuinfo.max_freq; policy->user_policy.max = policy->cpuinfo.max_freq;
policy->user_policy.governor = policy->governor;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#ifdef CONFIG_HOTPLUG_CPU
if (cpufreq_cpu_governor[cpu]){
policy->governor = cpufreq_cpu_governor[cpu];
dprintk("Restoring governor %s for cpu %d\n",
policy->governor->name, cpu);
}
#endif
for_each_cpu_mask(j, policy->cpus) { for_each_cpu_mask(j, policy->cpus) {
if (cpu == j) if (cpu == j)
continue; continue;
...@@ -873,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -873,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
/* set default policy */ /* set default policy */
ret = __cpufreq_set_policy(policy, &new_policy); ret = __cpufreq_set_policy(policy, &new_policy);
policy->user_policy.policy = policy->policy; policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor;
unlock_policy_rwsem_write(cpu); unlock_policy_rwsem_write(cpu);
...@@ -969,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev) ...@@ -969,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#ifdef CONFIG_HOTPLUG_CPU
cpufreq_cpu_governor[cpu] = data->governor;
#endif
/* if we have other CPUs still registered, we need to unlink them, /* if we have other CPUs still registered, we need to unlink them,
* or else wait_for_completion below will lock up. Clean the * or else wait_for_completion below will lock up. Clean the
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs * cpufreq_cpu_data[] while holding the lock, and remove the sysfs
...@@ -989,6 +1007,9 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev) ...@@ -989,6 +1007,9 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
if (j == cpu) if (j == cpu)
continue; continue;
dprintk("removing link for cpu %u\n", j); dprintk("removing link for cpu %u\n", j);
#ifdef CONFIG_HOTPLUG_CPU
cpufreq_cpu_governor[j] = data->governor;
#endif
cpu_sys_dev = get_cpu_sysdev(j); cpu_sys_dev = get_cpu_sysdev(j);
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data); cpufreq_cpu_put(data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment