diff options
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0611ae48e767..1d041aff4d48 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -903,7 +903,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) | |||
903 | 903 | ||
904 | #ifdef CONFIG_HOTPLUG_CPU | 904 | #ifdef CONFIG_HOTPLUG_CPU |
905 | static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, | 905 | static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, |
906 | struct device *dev) | 906 | struct device *dev, bool frozen) |
907 | { | 907 | { |
908 | struct cpufreq_policy *policy; | 908 | struct cpufreq_policy *policy; |
909 | int ret = 0, has_target = !!cpufreq_driver->target; | 909 | int ret = 0, has_target = !!cpufreq_driver->target; |
@@ -931,13 +931,18 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, | |||
931 | __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); | 931 | __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); |
932 | } | 932 | } |
933 | 933 | ||
934 | ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); | 934 | /* Don't touch sysfs links during light-weight init */ |
935 | if (ret) { | 935 | if (frozen) { |
936 | /* Drop the extra refcount that we took above */ | ||
936 | cpufreq_cpu_put(policy); | 937 | cpufreq_cpu_put(policy); |
937 | return ret; | 938 | return 0; |
938 | } | 939 | } |
939 | 940 | ||
940 | return 0; | 941 | ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); |
942 | if (ret) | ||
943 | cpufreq_cpu_put(policy); | ||
944 | |||
945 | return ret; | ||
941 | } | 946 | } |
942 | #endif | 947 | #endif |
943 | 948 | ||
@@ -972,16 +977,8 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) | |||
972 | kfree(policy); | 977 | kfree(policy); |
973 | } | 978 | } |
974 | 979 | ||
975 | /** | 980 | static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, |
976 | * cpufreq_add_dev - add a CPU device | 981 | bool frozen) |
977 | * | ||
978 | * Adds the cpufreq interface for a CPU device. | ||
979 | * | ||
980 | * The Oracle says: try running cpufreq registration/unregistration concurrently | ||
981 | * with with cpu hotplugging and all hell will break loose. Tried to clean this | ||
982 | * mess up, but more thorough testing is needed. - Mathieu | ||
983 | */ | ||
984 | static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | ||
985 | { | 982 | { |
986 | unsigned int j, cpu = dev->id; | 983 | unsigned int j, cpu = dev->id; |
987 | int ret = -ENOMEM; | 984 | int ret = -ENOMEM; |
@@ -1013,7 +1010,8 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
1013 | struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); | 1010 | struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); |
1014 | if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { | 1011 | if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { |
1015 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1012 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
1016 | return cpufreq_add_policy_cpu(cpu, sibling, dev); | 1013 | return cpufreq_add_policy_cpu(cpu, sibling, dev, |
1014 | frozen); | ||
1017 | } | 1015 | } |
1018 | } | 1016 | } |
1019 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1017 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
@@ -1079,9 +1077,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
1079 | } | 1077 | } |
1080 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1078 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
1081 | 1079 | ||
1082 | ret = cpufreq_add_dev_interface(cpu, policy, dev); | 1080 | if (!frozen) { |
1083 | if (ret) | 1081 | ret = cpufreq_add_dev_interface(cpu, policy, dev); |
1084 | goto err_out_unregister; | 1082 | if (ret) |
1083 | goto err_out_unregister; | ||
1084 | } | ||
1085 | 1085 | ||
1086 | cpufreq_init_policy(policy); | 1086 | cpufreq_init_policy(policy); |
1087 | 1087 | ||
@@ -1112,6 +1112,20 @@ module_out: | |||
1112 | return ret; | 1112 | return ret; |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | /** | ||
1116 | * cpufreq_add_dev - add a CPU device | ||
1117 | * | ||
1118 | * Adds the cpufreq interface for a CPU device. | ||
1119 | * | ||
1120 | * The Oracle says: try running cpufreq registration/unregistration concurrently | ||
1121 | * with with cpu hotplugging and all hell will break loose. Tried to clean this | ||
1122 | * mess up, but more thorough testing is needed. - Mathieu | ||
1123 | */ | ||
1124 | static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | ||
1125 | { | ||
1126 | return __cpufreq_add_dev(dev, sif, false); | ||
1127 | } | ||
1128 | |||
1115 | static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) | 1129 | static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) |
1116 | { | 1130 | { |
1117 | int j; | 1131 | int j; |
@@ -1130,7 +1144,7 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) | |||
1130 | } | 1144 | } |
1131 | 1145 | ||
1132 | static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, | 1146 | static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, |
1133 | unsigned int old_cpu) | 1147 | unsigned int old_cpu, bool frozen) |
1134 | { | 1148 | { |
1135 | struct device *cpu_dev; | 1149 | struct device *cpu_dev; |
1136 | unsigned long flags; | 1150 | unsigned long flags; |
@@ -1138,6 +1152,11 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, | |||
1138 | 1152 | ||
1139 | /* first sibling now owns the new sysfs dir */ | 1153 | /* first sibling now owns the new sysfs dir */ |
1140 | cpu_dev = get_cpu_device(cpumask_first(data->cpus)); | 1154 | cpu_dev = get_cpu_device(cpumask_first(data->cpus)); |
1155 | |||
1156 | /* Don't touch sysfs files during light-weight tear-down */ | ||
1157 | if (frozen) | ||
1158 | return cpu_dev->id; | ||
1159 | |||
1141 | sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); | 1160 | sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); |
1142 | ret = kobject_move(&data->kobj, &cpu_dev->kobj); | 1161 | ret = kobject_move(&data->kobj, &cpu_dev->kobj); |
1143 | if (ret) { | 1162 | if (ret) { |
@@ -1169,7 +1188,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, | |||
1169 | * This routine frees the rwsem before returning. | 1188 | * This routine frees the rwsem before returning. |
1170 | */ | 1189 | */ |
1171 | static int __cpufreq_remove_dev(struct device *dev, | 1190 | static int __cpufreq_remove_dev(struct device *dev, |
1172 | struct subsys_interface *sif) | 1191 | struct subsys_interface *sif, bool frozen) |
1173 | { | 1192 | { |
1174 | unsigned int cpu = dev->id, cpus; | 1193 | unsigned int cpu = dev->id, cpus; |
1175 | int new_cpu; | 1194 | int new_cpu; |
@@ -1208,17 +1227,20 @@ static int __cpufreq_remove_dev(struct device *dev, | |||
1208 | cpumask_clear_cpu(cpu, data->cpus); | 1227 | cpumask_clear_cpu(cpu, data->cpus); |
1209 | unlock_policy_rwsem_write(cpu); | 1228 | unlock_policy_rwsem_write(cpu); |
1210 | 1229 | ||
1211 | if (cpu != data->cpu) { | 1230 | if (cpu != data->cpu && !frozen) { |
1212 | sysfs_remove_link(&dev->kobj, "cpufreq"); | 1231 | sysfs_remove_link(&dev->kobj, "cpufreq"); |
1213 | } else if (cpus > 1) { | 1232 | } else if (cpus > 1) { |
1214 | 1233 | ||
1215 | new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu); | 1234 | new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu, frozen); |
1216 | if (new_cpu >= 0) { | 1235 | if (new_cpu >= 0) { |
1217 | WARN_ON(lock_policy_rwsem_write(cpu)); | 1236 | WARN_ON(lock_policy_rwsem_write(cpu)); |
1218 | update_policy_cpu(data, new_cpu); | 1237 | update_policy_cpu(data, new_cpu); |
1219 | unlock_policy_rwsem_write(cpu); | 1238 | unlock_policy_rwsem_write(cpu); |
1220 | pr_debug("%s: policy Kobject moved to cpu: %d " | 1239 | |
1221 | "from: %d\n",__func__, new_cpu, cpu); | 1240 | if (!frozen) { |
1241 | pr_debug("%s: policy Kobject moved to cpu: %d " | ||
1242 | "from: %d\n",__func__, new_cpu, cpu); | ||
1243 | } | ||
1222 | } | 1244 | } |
1223 | } | 1245 | } |
1224 | 1246 | ||
@@ -1266,7 +1288,7 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) | |||
1266 | if (cpu_is_offline(cpu)) | 1288 | if (cpu_is_offline(cpu)) |
1267 | return 0; | 1289 | return 0; |
1268 | 1290 | ||
1269 | retval = __cpufreq_remove_dev(dev, sif); | 1291 | retval = __cpufreq_remove_dev(dev, sif, false); |
1270 | return retval; | 1292 | return retval; |
1271 | } | 1293 | } |
1272 | 1294 | ||
@@ -1992,7 +2014,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, | |||
1992 | break; | 2014 | break; |
1993 | case CPU_DOWN_PREPARE: | 2015 | case CPU_DOWN_PREPARE: |
1994 | case CPU_DOWN_PREPARE_FROZEN: | 2016 | case CPU_DOWN_PREPARE_FROZEN: |
1995 | __cpufreq_remove_dev(dev, NULL); | 2017 | __cpufreq_remove_dev(dev, NULL, false); |
1996 | break; | 2018 | break; |
1997 | case CPU_DOWN_FAILED: | 2019 | case CPU_DOWN_FAILED: |
1998 | case CPU_DOWN_FAILED_FROZEN: | 2020 | case CPU_DOWN_FAILED_FROZEN: |