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.c93
1 files changed, 28 insertions, 65 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3dd4884c6f9e..3a64136bf21b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -916,58 +916,18 @@ static struct kobj_type ktype_cpufreq = {
916 .release = cpufreq_sysfs_release, 916 .release = cpufreq_sysfs_release,
917}; 917};
918 918
919static int add_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu) 919static int add_cpu_dev_symlink(struct cpufreq_policy *policy,
920 struct device *dev)
920{ 921{
921 struct device *cpu_dev; 922 dev_dbg(dev, "%s: Adding symlink\n", __func__);
922 923 return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
923 pr_debug("%s: Adding symlink for CPU: %u\n", __func__, cpu);
924
925 if (!policy)
926 return 0;
927
928 cpu_dev = get_cpu_device(cpu);
929 if (WARN_ON(!cpu_dev))
930 return 0;
931
932 return sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq");
933}
934
935static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu)
936{
937 struct device *cpu_dev;
938
939 pr_debug("%s: Removing symlink for CPU: %u\n", __func__, cpu);
940
941 cpu_dev = get_cpu_device(cpu);
942 if (WARN_ON(!cpu_dev))
943 return;
944
945 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
946} 924}
947 925
948/* Add/remove symlinks for all related CPUs */ 926static void remove_cpu_dev_symlink(struct cpufreq_policy *policy,
949static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy) 927 struct device *dev)
950{ 928{
951 unsigned int j; 929 dev_dbg(dev, "%s: Removing symlink\n", __func__);
952 int ret = 0; 930 sysfs_remove_link(&dev->kobj, "cpufreq");
953
954 /* Some related CPUs might not be present (physically hotplugged) */
955 for_each_cpu(j, policy->real_cpus) {
956 ret = add_cpu_dev_symlink(policy, j);
957 if (ret)
958 break;
959 }
960
961 return ret;
962}
963
964static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy)
965{
966 unsigned int j;
967
968 /* Some related CPUs might not be present (physically hotplugged) */
969 for_each_cpu(j, policy->real_cpus)
970 remove_cpu_dev_symlink(policy, j);
971} 931}
972 932
973static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) 933static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
@@ -999,7 +959,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
999 return ret; 959 return ret;
1000 } 960 }
1001 961
1002 return cpufreq_add_dev_symlink(policy); 962 return 0;
1003} 963}
1004 964
1005__weak struct cpufreq_governor *cpufreq_default_governor(void) 965__weak struct cpufreq_governor *cpufreq_default_governor(void)
@@ -1073,13 +1033,9 @@ static void handle_update(struct work_struct *work)
1073 1033
1074static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) 1034static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
1075{ 1035{
1076 struct device *dev = get_cpu_device(cpu);
1077 struct cpufreq_policy *policy; 1036 struct cpufreq_policy *policy;
1078 int ret; 1037 int ret;
1079 1038
1080 if (WARN_ON(!dev))
1081 return NULL;
1082
1083 policy = kzalloc(sizeof(*policy), GFP_KERNEL); 1039 policy = kzalloc(sizeof(*policy), GFP_KERNEL);
1084 if (!policy) 1040 if (!policy)
1085 return NULL; 1041 return NULL;
@@ -1133,7 +1089,6 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify)
1133 1089
1134 down_write(&policy->rwsem); 1090 down_write(&policy->rwsem);
1135 cpufreq_stats_free_table(policy); 1091 cpufreq_stats_free_table(policy);
1136 cpufreq_remove_dev_symlink(policy);
1137 kobj = &policy->kobj; 1092 kobj = &policy->kobj;
1138 cmp = &policy->kobj_unregister; 1093 cmp = &policy->kobj_unregister;
1139 up_write(&policy->rwsem); 1094 up_write(&policy->rwsem);
@@ -1215,8 +1170,8 @@ static int cpufreq_online(unsigned int cpu)
1215 if (new_policy) { 1170 if (new_policy) {
1216 /* related_cpus should at least include policy->cpus. */ 1171 /* related_cpus should at least include policy->cpus. */
1217 cpumask_copy(policy->related_cpus, policy->cpus); 1172 cpumask_copy(policy->related_cpus, policy->cpus);
1218 /* Remember CPUs present at the policy creation time. */ 1173 /* Clear mask of registered CPUs */
1219 cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask); 1174 cpumask_clear(policy->real_cpus);
1220 } 1175 }
1221 1176
1222 /* 1177 /*
@@ -1331,6 +1286,8 @@ out_free_policy:
1331 return ret; 1286 return ret;
1332} 1287}
1333 1288
1289static void cpufreq_offline(unsigned int cpu);
1290
1334/** 1291/**
1335 * cpufreq_add_dev - the cpufreq interface for a CPU device. 1292 * cpufreq_add_dev - the cpufreq interface for a CPU device.
1336 * @dev: CPU device. 1293 * @dev: CPU device.
@@ -1340,22 +1297,28 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1340{ 1297{
1341 struct cpufreq_policy *policy; 1298 struct cpufreq_policy *policy;
1342 unsigned cpu = dev->id; 1299 unsigned cpu = dev->id;
1300 int ret;
1343 1301
1344 dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu); 1302 dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu);
1345 1303
1346 if (cpu_online(cpu)) 1304 if (cpu_online(cpu)) {
1347 return cpufreq_online(cpu); 1305 ret = cpufreq_online(cpu);
1306 if (ret)
1307 return ret;
1308 }
1348 1309
1349 /* 1310 /* Create sysfs link on CPU registration */
1350 * A hotplug notifier will follow and we will handle it as CPU online
1351 * then. For now, just create the sysfs link, unless there is no policy
1352 * or the link is already present.
1353 */
1354 policy = per_cpu(cpufreq_cpu_data, cpu); 1311 policy = per_cpu(cpufreq_cpu_data, cpu);
1355 if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus)) 1312 if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus))
1356 return 0; 1313 return 0;
1357 1314
1358 return add_cpu_dev_symlink(policy, cpu); 1315 ret = add_cpu_dev_symlink(policy, dev);
1316 if (ret) {
1317 cpumask_clear_cpu(cpu, policy->real_cpus);
1318 cpufreq_offline(cpu);
1319 }
1320
1321 return ret;
1359} 1322}
1360 1323
1361static void cpufreq_offline(unsigned int cpu) 1324static void cpufreq_offline(unsigned int cpu)
@@ -1436,7 +1399,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
1436 cpufreq_offline(cpu); 1399 cpufreq_offline(cpu);
1437 1400
1438 cpumask_clear_cpu(cpu, policy->real_cpus); 1401 cpumask_clear_cpu(cpu, policy->real_cpus);
1439 remove_cpu_dev_symlink(policy, cpu); 1402 remove_cpu_dev_symlink(policy, dev);
1440 1403
1441 if (cpumask_empty(policy->real_cpus)) 1404 if (cpumask_empty(policy->real_cpus))
1442 cpufreq_policy_free(policy, true); 1405 cpufreq_policy_free(policy, true);