diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 71 |
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 | ||
1079 | static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) | 1079 | static 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 | ||
1095 | static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | 1107 | static 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 | ||
1312 | static 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 | |||
1336 | static int __cpufreq_remove_dev_prepare(struct device *dev, | 1322 | static 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 | } |