aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3938c7817095..ff57c40e9b8b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -41,7 +41,7 @@ static struct cpufreq_driver *cpufreq_driver;
41static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); 41static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
42#ifdef CONFIG_HOTPLUG_CPU 42#ifdef CONFIG_HOTPLUG_CPU
43/* This one keeps track of the previously set governor of a removed CPU */ 43/* This one keeps track of the previously set governor of a removed CPU */
44static DEFINE_PER_CPU(struct cpufreq_governor *, cpufreq_cpu_governor); 44static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
45#endif 45#endif
46static DEFINE_SPINLOCK(cpufreq_driver_lock); 46static DEFINE_SPINLOCK(cpufreq_driver_lock);
47 47
@@ -774,10 +774,12 @@ int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy,
774#ifdef CONFIG_SMP 774#ifdef CONFIG_SMP
775 unsigned long flags; 775 unsigned long flags;
776 unsigned int j; 776 unsigned int j;
777
778#ifdef CONFIG_HOTPLUG_CPU 777#ifdef CONFIG_HOTPLUG_CPU
779 if (per_cpu(cpufreq_cpu_governor, cpu)) { 778 struct cpufreq_governor *gov;
780 policy->governor = per_cpu(cpufreq_cpu_governor, cpu); 779
780 gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
781 if (gov) {
782 policy->governor = gov;
781 dprintk("Restoring governor %s for cpu %d\n", 783 dprintk("Restoring governor %s for cpu %d\n",
782 policy->governor->name, cpu); 784 policy->governor->name, cpu);
783 } 785 }
@@ -949,10 +951,13 @@ err_out_kobj_put:
949static int cpufreq_add_dev(struct sys_device *sys_dev) 951static int cpufreq_add_dev(struct sys_device *sys_dev)
950{ 952{
951 unsigned int cpu = sys_dev->id; 953 unsigned int cpu = sys_dev->id;
952 int ret = 0; 954 int ret = 0, found = 0;
953 struct cpufreq_policy *policy; 955 struct cpufreq_policy *policy;
954 unsigned long flags; 956 unsigned long flags;
955 unsigned int j; 957 unsigned int j;
958#ifdef CONFIG_HOTPLUG_CPU
959 int sibling;
960#endif
956 961
957 if (cpu_is_offline(cpu)) 962 if (cpu_is_offline(cpu))
958 return 0; 963 return 0;
@@ -999,7 +1004,19 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
999 INIT_WORK(&policy->update, handle_update); 1004 INIT_WORK(&policy->update, handle_update);
1000 1005
1001 /* Set governor before ->init, so that driver could check it */ 1006 /* Set governor before ->init, so that driver could check it */
1002 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 1007#ifdef CONFIG_HOTPLUG_CPU
1008 for_each_online_cpu(sibling) {
1009 struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
1010 if (cp && cp->governor &&
1011 (cpumask_test_cpu(cpu, cp->related_cpus))) {
1012 policy->governor = cp->governor;
1013 found = 1;
1014 break;
1015 }
1016 }
1017#endif
1018 if (!found)
1019 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
1003 /* call driver. From then on the cpufreq must be able 1020 /* call driver. From then on the cpufreq must be able
1004 * to accept all calls to ->verify and ->setpolicy for this CPU 1021 * to accept all calls to ->verify and ->setpolicy for this CPU
1005 */ 1022 */
@@ -1111,7 +1128,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1111#ifdef CONFIG_SMP 1128#ifdef CONFIG_SMP
1112 1129
1113#ifdef CONFIG_HOTPLUG_CPU 1130#ifdef CONFIG_HOTPLUG_CPU
1114 per_cpu(cpufreq_cpu_governor, cpu) = data->governor; 1131 strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name,
1132 CPUFREQ_NAME_LEN);
1115#endif 1133#endif
1116 1134
1117 /* if we have other CPUs still registered, we need to unlink them, 1135 /* if we have other CPUs still registered, we need to unlink them,
@@ -1135,7 +1153,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1135 continue; 1153 continue;
1136 dprintk("removing link for cpu %u\n", j); 1154 dprintk("removing link for cpu %u\n", j);
1137#ifdef CONFIG_HOTPLUG_CPU 1155#ifdef CONFIG_HOTPLUG_CPU
1138 per_cpu(cpufreq_cpu_governor, j) = data->governor; 1156 strncpy(per_cpu(cpufreq_cpu_governor, j),
1157 data->governor->name, CPUFREQ_NAME_LEN);
1139#endif 1158#endif
1140 cpu_sys_dev = get_cpu_sysdev(j); 1159 cpu_sys_dev = get_cpu_sysdev(j);
1141 sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); 1160 sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
@@ -1606,9 +1625,22 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor);
1606 1625
1607void cpufreq_unregister_governor(struct cpufreq_governor *governor) 1626void cpufreq_unregister_governor(struct cpufreq_governor *governor)
1608{ 1627{
1628#ifdef CONFIG_HOTPLUG_CPU
1629 int cpu;
1630#endif
1631
1609 if (!governor) 1632 if (!governor)
1610 return; 1633 return;
1611 1634
1635#ifdef CONFIG_HOTPLUG_CPU
1636 for_each_present_cpu(cpu) {
1637 if (cpu_online(cpu))
1638 continue;
1639 if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
1640 strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
1641 }
1642#endif
1643
1612 mutex_lock(&cpufreq_governor_mutex); 1644 mutex_lock(&cpufreq_governor_mutex);
1613 list_del(&governor->governor_list); 1645 list_del(&governor->governor_list);
1614 mutex_unlock(&cpufreq_governor_mutex); 1646 mutex_unlock(&cpufreq_governor_mutex);