diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-07-28 21:03:44 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-07-31 15:59:37 -0400 |
commit | 0b275352872b2641ed5c94d0f0f8c7e907bf3e3f (patch) | |
tree | 781d001c4a083f578ab252a5ef7a09f90c2f0a70 | |
parent | 227942809b52f23cda414858b635c0285f11de00 (diff) |
cpufreq: Separate CPU device registration from CPU online
To separate the CPU online interface from the CPU device
registration, split cpufreq_online() out of cpufreq_add_dev()
and make cpufreq_cpu_callback() call the former, while
cpufreq_add_dev() itself will only be used as the CPU device
addition subsystem interface callback.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Suggested-by: Russell King <linux@arm.linux.org.uk>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 90 |
1 files changed, 47 insertions, 43 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0618522d4863..0d46b557c016 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -1191,36 +1191,15 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify) | |||
1191 | kfree(policy); | 1191 | kfree(policy); |
1192 | } | 1192 | } |
1193 | 1193 | ||
1194 | /** | 1194 | static int cpufreq_online(unsigned int cpu) |
1195 | * cpufreq_add_dev - add a CPU device | ||
1196 | * | ||
1197 | * Adds the cpufreq interface for a CPU device. | ||
1198 | * | ||
1199 | * The Oracle says: try running cpufreq registration/unregistration concurrently | ||
1200 | * with with cpu hotplugging and all hell will break loose. Tried to clean this | ||
1201 | * mess up, but more thorough testing is needed. - Mathieu | ||
1202 | */ | ||
1203 | static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | ||
1204 | { | 1195 | { |
1205 | unsigned int j, cpu = dev->id; | ||
1206 | int ret; | ||
1207 | struct cpufreq_policy *policy; | 1196 | struct cpufreq_policy *policy; |
1208 | unsigned long flags; | ||
1209 | bool recover_policy; | 1197 | bool recover_policy; |
1198 | unsigned long flags; | ||
1199 | unsigned int j; | ||
1200 | int ret; | ||
1210 | 1201 | ||
1211 | pr_debug("adding CPU %u\n", cpu); | 1202 | pr_debug("%s: bringing CPU%u online\n", __func__, cpu); |
1212 | |||
1213 | if (cpu_is_offline(cpu)) { | ||
1214 | /* | ||
1215 | * Only possible if we are here from the subsys_interface add | ||
1216 | * callback. A hotplug notifier will follow and we will handle | ||
1217 | * it as CPU online then. For now, just create the sysfs link, | ||
1218 | * unless there is no policy or the link is already present. | ||
1219 | */ | ||
1220 | policy = per_cpu(cpufreq_cpu_data, cpu); | ||
1221 | return policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus) | ||
1222 | ? add_cpu_dev_symlink(policy, cpu) : 0; | ||
1223 | } | ||
1224 | 1203 | ||
1225 | /* Check if this CPU already has a policy to manage it */ | 1204 | /* Check if this CPU already has a policy to manage it */ |
1226 | policy = per_cpu(cpufreq_cpu_data, cpu); | 1205 | policy = per_cpu(cpufreq_cpu_data, cpu); |
@@ -1377,6 +1356,35 @@ out_free_policy: | |||
1377 | return ret; | 1356 | return ret; |
1378 | } | 1357 | } |
1379 | 1358 | ||
1359 | /** | ||
1360 | * cpufreq_add_dev - the cpufreq interface for a CPU device. | ||
1361 | * @dev: CPU device. | ||
1362 | * @sif: Subsystem interface structure pointer (not used) | ||
1363 | */ | ||
1364 | static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | ||
1365 | { | ||
1366 | unsigned cpu = dev->id; | ||
1367 | int ret; | ||
1368 | |||
1369 | dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu); | ||
1370 | |||
1371 | if (cpu_online(cpu)) { | ||
1372 | ret = cpufreq_online(cpu); | ||
1373 | } else { | ||
1374 | /* | ||
1375 | * A hotplug notifier will follow and we will handle it as CPU | ||
1376 | * online then. For now, just create the sysfs link, unless | ||
1377 | * there is no policy or the link is already present. | ||
1378 | */ | ||
1379 | struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); | ||
1380 | |||
1381 | ret = policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus) | ||
1382 | ? add_cpu_dev_symlink(policy, cpu) : 0; | ||
1383 | } | ||
1384 | |||
1385 | return ret; | ||
1386 | } | ||
1387 | |||
1380 | static void cpufreq_offline_prepare(unsigned int cpu) | 1388 | static void cpufreq_offline_prepare(unsigned int cpu) |
1381 | { | 1389 | { |
1382 | struct cpufreq_policy *policy; | 1390 | struct cpufreq_policy *policy; |
@@ -2340,27 +2348,23 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, | |||
2340 | unsigned long action, void *hcpu) | 2348 | unsigned long action, void *hcpu) |
2341 | { | 2349 | { |
2342 | unsigned int cpu = (unsigned long)hcpu; | 2350 | unsigned int cpu = (unsigned long)hcpu; |
2343 | struct device *dev; | ||
2344 | 2351 | ||
2345 | dev = get_cpu_device(cpu); | 2352 | switch (action & ~CPU_TASKS_FROZEN) { |
2346 | if (dev) { | 2353 | case CPU_ONLINE: |
2347 | switch (action & ~CPU_TASKS_FROZEN) { | 2354 | cpufreq_online(cpu); |
2348 | case CPU_ONLINE: | 2355 | break; |
2349 | cpufreq_add_dev(dev, NULL); | ||
2350 | break; | ||
2351 | 2356 | ||
2352 | case CPU_DOWN_PREPARE: | 2357 | case CPU_DOWN_PREPARE: |
2353 | cpufreq_offline_prepare(cpu); | 2358 | cpufreq_offline_prepare(cpu); |
2354 | break; | 2359 | break; |
2355 | 2360 | ||
2356 | case CPU_POST_DEAD: | 2361 | case CPU_POST_DEAD: |
2357 | cpufreq_offline_finish(cpu); | 2362 | cpufreq_offline_finish(cpu); |
2358 | break; | 2363 | break; |
2359 | 2364 | ||
2360 | case CPU_DOWN_FAILED: | 2365 | case CPU_DOWN_FAILED: |
2361 | cpufreq_add_dev(dev, NULL); | 2366 | cpufreq_online(cpu); |
2362 | break; | 2367 | break; |
2363 | } | ||
2364 | } | 2368 | } |
2365 | return NOTIFY_OK; | 2369 | return NOTIFY_OK; |
2366 | } | 2370 | } |