[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=8671 Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dave Jones <davej@redhat.com>
This commit is contained in:
parent
91973de736
commit
084f349394
|
@ -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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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)
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue