This patch cleans up the hot-cpu callback interface of cpufreq so that lock_cpu_hotplug won't be called from a cpu_up or a cpu_down. Signed-off-by : Gautham R Shenoy Index: current/include/linux/cpufreq.h =================================================================== --- current.orig/include/linux/cpufreq.h 2006-08-06 23:50:11.000000000 +0530 +++ current/include/linux/cpufreq.h 2006-08-24 14:59:59.000000000 +0530 @@ -164,6 +164,9 @@ struct cpufreq_governor { /* pass a target to the cpufreq driver */ +extern int cpufreq_driver_target_cpulocked(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); extern int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); @@ -253,8 +256,10 @@ struct freq_attr { * CPUFREQ 2.6. INTERFACE * *********************************************************************/ int cpufreq_set_policy(struct cpufreq_policy *policy); +int cpufreq_set_policy_cpulocked(struct cpufreq_policy *policy); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_update_policy(unsigned int cpu); +int cpufreq_update_policy_cpulocked(unsigned int cpu); /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */ unsigned int cpufreq_get(unsigned int cpu); Index: current/drivers/cpufreq/cpufreq.c =================================================================== --- current.orig/drivers/cpufreq/cpufreq.c 2006-08-06 23:50:11.000000000 +0530 +++ current/drivers/cpufreq/cpufreq.c 2006-08-24 14:59:59.000000000 +0530 @@ -744,7 +744,7 @@ static int cpufreq_add_dev (struct sys_d mutex_unlock(&policy->lock); /* set default policy */ - ret = cpufreq_set_policy(&new_policy); + ret = cpufreq_set_policy_cpulocked(&new_policy); if (ret) { dprintk("setting policy failed\n"); goto err_out_unregister; @@ -1246,27 +1246,37 @@ int __cpufreq_driver_target(struct cpufr EXPORT_SYMBOL_GPL(__cpufreq_driver_target); int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + int ret=0; + lock_cpu_hotplug(); + ret= cpufreq_driver_target_cpulocked(policy,target_freq,relation); + unlock_cpu_hotplug(); + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_driver_target); + +int cpufreq_driver_target_cpulocked(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - int ret; + int ret=0; policy = cpufreq_cpu_get(policy->cpu); if (!policy) return -EINVAL; - lock_cpu_hotplug(); mutex_lock(&policy->lock); ret = __cpufreq_driver_target(policy, target_freq, relation); mutex_unlock(&policy->lock); - unlock_cpu_hotplug(); cpufreq_cpu_put(policy); return ret; } -EXPORT_SYMBOL_GPL(cpufreq_driver_target); +EXPORT_SYMBOL_GPL(cpufreq_driver_target_cpulocked); /* * Locking: Must be called with the lock_cpu_hotplug() lock held @@ -1450,6 +1460,15 @@ error_out: */ int cpufreq_set_policy(struct cpufreq_policy *policy) { + int ret=0; + lock_cpu_hotplug(); + ret = cpufreq_set_policy_cpulocked(policy); + unlock_cpu_hotplug(); + return ret; +} + +int cpufreq_set_policy_cpulocked(struct cpufreq_policy *policy) +{ int ret = 0; struct cpufreq_policy *data; @@ -1460,7 +1479,6 @@ int cpufreq_set_policy(struct cpufreq_po if (!data) return -EINVAL; - lock_cpu_hotplug(); /* lock this CPU */ mutex_lock(&data->lock); @@ -1473,7 +1491,6 @@ int cpufreq_set_policy(struct cpufreq_po mutex_unlock(&data->lock); - unlock_cpu_hotplug(); cpufreq_cpu_put(data); return ret; @@ -1482,13 +1499,15 @@ EXPORT_SYMBOL(cpufreq_set_policy); /** - * cpufreq_update_policy - re-evaluate an existing cpufreq policy + * cpufreq_update_policy_cpulocked - re-evaluate an existing cpufreq + * policy. + * To be called with lock_cpu_hotplug() held. * @cpu: CPU which shall be re-evaluated * * Usefull for policy notifiers which have different necessities * at different times. */ -int cpufreq_update_policy(unsigned int cpu) +int cpufreq_update_policy_cpulocked(unsigned int cpu) { struct cpufreq_policy *data = cpufreq_cpu_get(cpu); struct cpufreq_policy policy; @@ -1497,7 +1516,6 @@ int cpufreq_update_policy(unsigned int c if (!data) return -ENODEV; - lock_cpu_hotplug(); mutex_lock(&data->lock); dprintk("updating policy for CPU %u\n", cpu); @@ -1523,10 +1541,28 @@ int cpufreq_update_policy(unsigned int c ret = __cpufreq_set_policy(data, &policy); mutex_unlock(&data->lock); - unlock_cpu_hotplug(); cpufreq_cpu_put(data); return ret; } +EXPORT_SYMBOL(cpufreq_update_policy_cpulocked); + +/** + * cpufreq_update_policy - re-evaluate an existing cpufreq + * policy. + * Must be called with lock_cpu_hotplug() *not* being held. + * @cpu: CPU which shall be re-evaluated + * + * Usefull for policy notifiers which have different necessities + * at different times. + */ +int cpufreq_update_policy(unsigned int cpu) +{ + int ret=0; + lock_cpu_hotplug(); + cpufreq_update_policy_cpulocked(cpu); + unlock_cpu_hotplug(); + return ret; +} EXPORT_SYMBOL(cpufreq_update_policy); #ifdef CONFIG_HOTPLUG_CPU @@ -1553,8 +1589,8 @@ static int cpufreq_cpu_callback(struct n */ policy = cpufreq_cpu_data[cpu]; if (policy) { - cpufreq_driver_target(policy, policy->min, - CPUFREQ_RELATION_H); + cpufreq_driver_target_cpulocked(policy, + policy->min, CPUFREQ_RELATION_H); } break; case CPU_DEAD: Index: current/drivers/cpufreq/cpufreq_stats.c =================================================================== --- current.orig/drivers/cpufreq/cpufreq_stats.c 2006-08-06 23:50:11.000000000 +0530 +++ current/drivers/cpufreq/cpufreq_stats.c 2006-08-24 14:59:59.000000000 +0530 @@ -309,7 +309,7 @@ static int cpufreq_stat_cpu_callback(str switch (action) { case CPU_ONLINE: - cpufreq_update_policy(cpu); + cpufreq_update_policy_cpulocked(cpu); break; case CPU_DEAD: cpufreq_stats_free_table(cpu);