*/
static struct cpufreq_driver *cpufreq_driver;
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);
/*
unlock_policy_rwsem_write(cpu);
goto err_out;
}
+ policy->user_policy.min = policy->cpuinfo.min_freq;
+ policy->user_policy.max = policy->cpuinfo.max_freq;
#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) {
if (cpu == j)
continue;
/* set up files for this cpu device */
drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) {
- sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+ ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+ if (ret)
+ goto err_out_driver_exit;
drv_attr++;
}
- if (cpufreq_driver->get)
- sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
- if (cpufreq_driver->target)
- sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+ if (cpufreq_driver->get){
+ ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
+ if (cpufreq_driver->target){
+ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
spin_lock_irqsave(&cpufreq_driver_lock, flags);
for_each_cpu_mask(j, policy->cpus) {
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
- unlock_policy_rwsem_write(cpu);
/* set default policy */
- ret = cpufreq_set_policy(&new_policy);
+ ret = __cpufreq_set_policy(policy, &new_policy);
+ policy->user_policy.policy = policy->policy;
+ policy->user_policy.governor = policy->governor;
+
+ unlock_policy_rwsem_write(cpu);
+
if (ret) {
dprintk("setting policy failed\n");
goto err_out_unregister;
}
#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,
* or else wait_for_completion below will lock up. Clean the
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs
if (j == cpu)
continue;
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);
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data);
return ret;
}
-/**
- * cpufreq_set_policy - set a new CPUFreq policy
- * @policy: policy to be set.
- *
- * Sets a new CPU frequency and voltage scaling policy.
- */
-int cpufreq_set_policy(struct cpufreq_policy *policy)
-{
- int ret = 0;
- struct cpufreq_policy *data;
-
- if (!policy)
- return -EINVAL;
-
- data = cpufreq_cpu_get(policy->cpu);
- if (!data)
- return -EINVAL;
-
- if (unlikely(lock_policy_rwsem_write(policy->cpu)))
- return -EINVAL;
-
-
- ret = __cpufreq_set_policy(data, policy);
- data->user_policy.min = data->min;
- data->user_policy.max = data->max;
- data->user_policy.policy = data->policy;
- data->user_policy.governor = data->governor;
-
- unlock_policy_rwsem_write(policy->cpu);
-
- cpufreq_cpu_put(data);
-
- return ret;
-}
-EXPORT_SYMBOL(cpufreq_set_policy);
-
-
/**
* cpufreq_update_policy - re-evaluate an existing cpufreq policy
* @cpu: CPU which shall be re-evaluated
{
unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev;
- struct cpufreq_policy *policy;
sys_dev = get_cpu_sysdev(cpu);
if (sys_dev) {
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
cpufreq_add_dev(sys_dev);
break;
case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
if (unlikely(lock_policy_rwsem_write(cpu)))
BUG();
- policy = cpufreq_cpu_data[cpu];
- if (policy) {
- __cpufreq_driver_target(policy, policy->min,
- CPUFREQ_RELATION_H);
- }
__cpufreq_remove_dev(sys_dev);
break;
case CPU_DOWN_FAILED:
+ case CPU_DOWN_FAILED_FROZEN:
cpufreq_add_dev(sys_dev);
break;
}