aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-07-28 21:03:44 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-07-31 15:59:37 -0400
commit0b275352872b2641ed5c94d0f0f8c7e907bf3e3f (patch)
tree781d001c4a083f578ab252a5ef7a09f90c2f0a70
parent227942809b52f23cda414858b635c0285f11de00 (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.c90
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/** 1194static 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 */
1203static 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 */
1364static 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
1380static void cpufreq_offline_prepare(unsigned int cpu) 1388static 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}