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.c71
1 files changed, 33 insertions, 38 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ec25ca607679..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)
@@ -1153,12 +1165,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1153 * the creation of a brand new one. So we need to perform this update 1165 * the creation of a brand new one. So we need to perform this update
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 WARN_ON(kobject_move(&policy->kobj, &dev->kobj)); 1170 else
1159 } else {
1160 policy->cpu = cpu; 1171 policy->cpu = cpu;
1161 }
1162 1172
1163 cpumask_copy(policy->cpus, cpumask_of(cpu)); 1173 cpumask_copy(policy->cpus, cpumask_of(cpu));
1164 1174
@@ -1309,35 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1309 return __cpufreq_add_dev(dev, sif); 1319 return __cpufreq_add_dev(dev, sif);
1310} 1320}
1311 1321
1312static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1313 unsigned int old_cpu)
1314{
1315 struct device *cpu_dev;
1316 int ret;
1317
1318 /* first sibling now owns the new sysfs dir */
1319 cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
1320
1321 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1322 ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
1323 if (ret) {
1324 pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
1325
1326 if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"))
1327 pr_err("%s: Failed to restore kobj link to cpu:%d\n",
1328 __func__, cpu_dev->id);
1329
1330 return ret;
1331 }
1332
1333 return cpu_dev->id;
1334}
1335
1336static int __cpufreq_remove_dev_prepare(struct device *dev, 1322static int __cpufreq_remove_dev_prepare(struct device *dev,
1337 struct subsys_interface *sif) 1323 struct subsys_interface *sif)
1338{ 1324{
1339 unsigned int cpu = dev->id, cpus; 1325 unsigned int cpu = dev->id, cpus;
1340 int new_cpu, ret; 1326 int ret;
1341 unsigned long flags; 1327 unsigned long flags;
1342 struct cpufreq_policy *policy; 1328 struct cpufreq_policy *policy;
1343 1329
@@ -1377,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
1377 if (cpu != policy->cpu) { 1363 if (cpu != policy->cpu) {
1378 sysfs_remove_link(&dev->kobj, "cpufreq"); 1364 sysfs_remove_link(&dev->kobj, "cpufreq");
1379 } else if (cpus > 1) { 1365 } else if (cpus > 1) {
1380 new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); 1366 /* Nominate new CPU */
1381 if (new_cpu >= 0) { 1367 int new_cpu = cpumask_any_but(policy->cpus, cpu);
1382 update_policy_cpu(policy, new_cpu); 1368 struct device *cpu_dev = get_cpu_device(new_cpu);
1383 1369
1384 if (!cpufreq_suspended) 1370 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1385 pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", 1371 ret = update_policy_cpu(policy, new_cpu, cpu_dev);
1386 __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;
1387 } 1378 }
1379
1380 if (!cpufreq_suspended)
1381 pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
1382 __func__, new_cpu, cpu);
1388 } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) { 1383 } else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
1389 cpufreq_driver->stop_cpu(policy); 1384 cpufreq_driver->stop_cpu(policy);
1390 } 1385 }