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.c78
1 files changed, 35 insertions, 43 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index aed2b0cb83dc..d9fdeddcef96 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
1076 kfree(policy); 1076 kfree(policy);
1077} 1077}
1078 1078
1079static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) 1079static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu,
1080 struct device *cpu_dev)
1080{ 1081{
1082 int ret;
1083
1081 if (WARN_ON(cpu == policy->cpu)) 1084 if (WARN_ON(cpu == policy->cpu))
1082 return; 1085 return 0;
1086
1087 /* Move kobject to the new policy->cpu */
1088 ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
1089 if (ret) {
1090 pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
1091 return ret;
1092 }
1083 1093
1084 down_write(&policy->rwsem); 1094 down_write(&policy->rwsem);
1085 1095
@@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
1090 1100
1091 blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1101 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1092 CPUFREQ_UPDATE_POLICY_CPU, policy); 1102 CPUFREQ_UPDATE_POLICY_CPU, policy);
1103
1104 return 0;
1093} 1105}
1094 1106
1095static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) 1107static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
@@ -1154,7 +1166,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1154 * by invoking update_policy_cpu(). 1166 * by invoking update_policy_cpu().
1155 */ 1167 */
1156 if (recover_policy && cpu != policy->cpu) 1168 if (recover_policy && cpu != policy->cpu)
1157 update_policy_cpu(policy, cpu); 1169 WARN_ON(update_policy_cpu(policy, cpu, dev));
1158 else 1170 else
1159 policy->cpu = cpu; 1171 policy->cpu = cpu;
1160 1172
@@ -1307,38 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1307 return __cpufreq_add_dev(dev, sif); 1319 return __cpufreq_add_dev(dev, sif);
1308} 1320}
1309 1321
1310static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1311 unsigned int old_cpu)
1312{
1313 struct device *cpu_dev;
1314 int ret;
1315
1316 /* first sibling now owns the new sysfs dir */
1317 cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
1318
1319 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1320 ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
1321 if (ret) {
1322 pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
1323
1324 down_write(&policy->rwsem);
1325 cpumask_set_cpu(old_cpu, policy->cpus);
1326 up_write(&policy->rwsem);
1327
1328 ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
1329 "cpufreq");
1330
1331 return -EINVAL;
1332 }
1333
1334 return cpu_dev->id;
1335}
1336
1337static int __cpufreq_remove_dev_prepare(struct device *dev, 1322static int __cpufreq_remove_dev_prepare(struct device *dev,
1338 struct subsys_interface *sif) 1323 struct subsys_interface *sif)
1339{ 1324{
1340 unsigned int cpu = dev->id, cpus; 1325 unsigned int cpu = dev->id, cpus;
1341 int new_cpu, ret; 1326 int ret;
1342 unsigned long flags; 1327 unsigned long flags;
1343 struct cpufreq_policy *policy; 1328 struct cpufreq_policy *policy;
1344 1329
@@ -1378,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
1378 if (cpu != policy->cpu) { 1363 if (cpu != policy->cpu) {
1379 sysfs_remove_link(&dev->kobj, "cpufreq"); 1364 sysfs_remove_link(&dev->kobj, "cpufreq");
1380 } else if (cpus > 1) { 1365 } else if (cpus > 1) {
1381 new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); 1366 /* Nominate new CPU */
1382 if (new_cpu >= 0) { 1367 int new_cpu = cpumask_any_but(policy->cpus, cpu);
1383 update_policy_cpu(policy, new_cpu); 1368 struct device *cpu_dev = get_cpu_device(new_cpu);
1384 1369
1385 if (!cpufreq_suspended) 1370 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1386 pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", 1371 ret = update_policy_cpu(policy, new_cpu, cpu_dev);
1387 __func__, new_cpu, cpu); 1372 if (ret) {
1373 if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
1374 "cpufreq"))
1375 pr_err("%s: Failed to restore kobj link to cpu:%d\n",
1376 __func__, cpu_dev->id);
1377 return ret;
1388 } 1378 }
1379
1380 if (!cpufreq_suspended)
1381 pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
1382 __func__, new_cpu, cpu);
1389 } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) { 1383 } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
1390 cpufreq_driver->stop_cpu(policy); 1384 cpufreq_driver->stop_cpu(policy);
1391 } 1385 }
@@ -2242,10 +2236,8 @@ int cpufreq_update_policy(unsigned int cpu)
2242 struct cpufreq_policy new_policy; 2236 struct cpufreq_policy new_policy;
2243 int ret; 2237 int ret;
2244 2238
2245 if (!policy) { 2239 if (!policy)
2246 ret = -ENODEV; 2240 return -ENODEV;
2247 goto no_policy;
2248 }
2249 2241
2250 down_write(&policy->rwsem); 2242 down_write(&policy->rwsem);
2251 2243
@@ -2264,7 +2256,7 @@ int cpufreq_update_policy(unsigned int cpu)
2264 new_policy.cur = cpufreq_driver->get(cpu); 2256 new_policy.cur = cpufreq_driver->get(cpu);
2265 if (WARN_ON(!new_policy.cur)) { 2257 if (WARN_ON(!new_policy.cur)) {
2266 ret = -EIO; 2258 ret = -EIO;
2267 goto no_policy; 2259 goto unlock;
2268 } 2260 }
2269 2261
2270 if (!policy->cur) { 2262 if (!policy->cur) {
@@ -2279,10 +2271,10 @@ int cpufreq_update_policy(unsigned int cpu)
2279 2271
2280 ret = cpufreq_set_policy(policy, &new_policy); 2272 ret = cpufreq_set_policy(policy, &new_policy);
2281 2273
2274unlock:
2282 up_write(&policy->rwsem); 2275 up_write(&policy->rwsem);
2283 2276
2284 cpufreq_cpu_put(policy); 2277 cpufreq_cpu_put(policy);
2285no_policy:
2286 return ret; 2278 return ret;
2287} 2279}
2288EXPORT_SYMBOL(cpufreq_update_policy); 2280EXPORT_SYMBOL(cpufreq_update_policy);