Skip to content

Commit

Permalink
cpufreq: Separate CPU device registration from CPU online
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rafael J. Wysocki committed Jul 31, 2015
1 parent 2279428 commit 0b27535
Showing 1 changed file with 47 additions and 43 deletions.
90 changes: 47 additions & 43 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,36 +1191,15 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify)
kfree(policy);
}

/**
* cpufreq_add_dev - add a CPU device
*
* Adds the cpufreq interface for a CPU device.
*
* The Oracle says: try running cpufreq registration/unregistration concurrently
* with with cpu hotplugging and all hell will break loose. Tried to clean this
* mess up, but more thorough testing is needed. - Mathieu
*/
static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
static int cpufreq_online(unsigned int cpu)
{
unsigned int j, cpu = dev->id;
int ret;
struct cpufreq_policy *policy;
unsigned long flags;
bool recover_policy;
unsigned long flags;
unsigned int j;
int ret;

pr_debug("adding CPU %u\n", cpu);

if (cpu_is_offline(cpu)) {
/*
* Only possible if we are here from the subsys_interface add
* callback. A hotplug notifier will follow and we will handle
* it as CPU online then. For now, just create the sysfs link,
* unless there is no policy or the link is already present.
*/
policy = per_cpu(cpufreq_cpu_data, cpu);
return policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus)
? add_cpu_dev_symlink(policy, cpu) : 0;
}
pr_debug("%s: bringing CPU%u online\n", __func__, cpu);

/* Check if this CPU already has a policy to manage it */
policy = per_cpu(cpufreq_cpu_data, cpu);
Expand Down Expand Up @@ -1377,6 +1356,35 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
return ret;
}

/**
* cpufreq_add_dev - the cpufreq interface for a CPU device.
* @dev: CPU device.
* @sif: Subsystem interface structure pointer (not used)
*/
static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
{
unsigned cpu = dev->id;
int ret;

dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu);

if (cpu_online(cpu)) {
ret = cpufreq_online(cpu);
} else {
/*
* A hotplug notifier will follow and we will handle it as CPU
* online then. For now, just create the sysfs link, unless
* there is no policy or the link is already present.
*/
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);

ret = policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus)
? add_cpu_dev_symlink(policy, cpu) : 0;
}

return ret;
}

static void cpufreq_offline_prepare(unsigned int cpu)
{
struct cpufreq_policy *policy;
Expand Down Expand Up @@ -2340,27 +2348,23 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
struct device *dev;

dev = get_cpu_device(cpu);
if (dev) {
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE:
cpufreq_add_dev(dev, NULL);
break;
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE:
cpufreq_online(cpu);
break;

case CPU_DOWN_PREPARE:
cpufreq_offline_prepare(cpu);
break;
case CPU_DOWN_PREPARE:
cpufreq_offline_prepare(cpu);
break;

case CPU_POST_DEAD:
cpufreq_offline_finish(cpu);
break;
case CPU_POST_DEAD:
cpufreq_offline_finish(cpu);
break;

case CPU_DOWN_FAILED:
cpufreq_add_dev(dev, NULL);
break;
}
case CPU_DOWN_FAILED:
cpufreq_online(cpu);
break;
}
return NOTIFY_OK;
}
Expand Down

0 comments on commit 0b27535

Please sign in to comment.