Merge branches 'pm-cpufreq' and 'pm-sleep' containing PM fixes
* pm-cpufreq: cpufreq: Use CONFIG_CPU_FREQ_DEFAULT_* to set initial policy for setpolicy drivers cpufreq: remove sysfs files for CPUs which failed to come back after resume * pm-sleep: PM / sleep: Fix memory leak in pm_vt_switch_unregister().
This commit is contained in:
Коммит
1a6725359e
|
@ -828,6 +828,12 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
memcpy(&new_policy, policy, sizeof(*policy));
|
memcpy(&new_policy, policy, sizeof(*policy));
|
||||||
|
|
||||||
|
/* Use the default policy if its valid. */
|
||||||
|
if (cpufreq_driver->setpolicy)
|
||||||
|
cpufreq_parse_governor(policy->governor->name,
|
||||||
|
&new_policy.policy, NULL);
|
||||||
|
|
||||||
/* assure that the starting sequence is run in cpufreq_set_policy */
|
/* assure that the starting sequence is run in cpufreq_set_policy */
|
||||||
policy->governor = NULL;
|
policy->governor = NULL;
|
||||||
|
|
||||||
|
@ -845,8 +851,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
|
static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
|
||||||
unsigned int cpu, struct device *dev,
|
unsigned int cpu, struct device *dev)
|
||||||
bool frozen)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -877,11 +882,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't touch sysfs links during light-weight init */
|
return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
|
||||||
if (!frozen)
|
|
||||||
ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -926,6 +927,27 @@ err_free_policy:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
|
||||||
|
{
|
||||||
|
struct kobject *kobj;
|
||||||
|
struct completion *cmp;
|
||||||
|
|
||||||
|
down_read(&policy->rwsem);
|
||||||
|
kobj = &policy->kobj;
|
||||||
|
cmp = &policy->kobj_unregister;
|
||||||
|
up_read(&policy->rwsem);
|
||||||
|
kobject_put(kobj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to make sure that the underlying kobj is
|
||||||
|
* actually not referenced anymore by anybody before we
|
||||||
|
* proceed with unloading.
|
||||||
|
*/
|
||||||
|
pr_debug("waiting for dropping of refcount\n");
|
||||||
|
wait_for_completion(cmp);
|
||||||
|
pr_debug("wait complete\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
free_cpumask_var(policy->related_cpus);
|
free_cpumask_var(policy->related_cpus);
|
||||||
|
@ -986,7 +1008,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
|
||||||
list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
|
list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
|
||||||
if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
|
if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
|
||||||
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
|
ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
|
||||||
up_read(&cpufreq_rwsem);
|
up_read(&cpufreq_rwsem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +1118,10 @@ err_get_freq:
|
||||||
if (cpufreq_driver->exit)
|
if (cpufreq_driver->exit)
|
||||||
cpufreq_driver->exit(policy);
|
cpufreq_driver->exit(policy);
|
||||||
err_set_policy_cpu:
|
err_set_policy_cpu:
|
||||||
|
if (frozen)
|
||||||
|
cpufreq_policy_put_kobj(policy);
|
||||||
cpufreq_policy_free(policy);
|
cpufreq_policy_free(policy);
|
||||||
|
|
||||||
nomem_out:
|
nomem_out:
|
||||||
up_read(&cpufreq_rwsem);
|
up_read(&cpufreq_rwsem);
|
||||||
|
|
||||||
|
@ -1118,7 +1143,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
|
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
|
||||||
unsigned int old_cpu, bool frozen)
|
unsigned int old_cpu)
|
||||||
{
|
{
|
||||||
struct device *cpu_dev;
|
struct device *cpu_dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1126,10 +1151,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
|
||||||
/* first sibling now owns the new sysfs dir */
|
/* first sibling now owns the new sysfs dir */
|
||||||
cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
|
cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
|
||||||
|
|
||||||
/* Don't touch sysfs files during light-weight tear-down */
|
|
||||||
if (frozen)
|
|
||||||
return cpu_dev->id;
|
|
||||||
|
|
||||||
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
|
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
|
||||||
ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
|
ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1196,7 +1217,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
|
||||||
if (!frozen)
|
if (!frozen)
|
||||||
sysfs_remove_link(&dev->kobj, "cpufreq");
|
sysfs_remove_link(&dev->kobj, "cpufreq");
|
||||||
} else if (cpus > 1) {
|
} else if (cpus > 1) {
|
||||||
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
|
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
|
||||||
if (new_cpu >= 0) {
|
if (new_cpu >= 0) {
|
||||||
update_policy_cpu(policy, new_cpu);
|
update_policy_cpu(policy, new_cpu);
|
||||||
|
|
||||||
|
@ -1218,8 +1239,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct cpufreq_policy *policy;
|
struct cpufreq_policy *policy;
|
||||||
struct kobject *kobj;
|
|
||||||
struct completion *cmp;
|
|
||||||
|
|
||||||
read_lock_irqsave(&cpufreq_driver_lock, flags);
|
read_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
policy = per_cpu(cpufreq_cpu_data, cpu);
|
policy = per_cpu(cpufreq_cpu_data, cpu);
|
||||||
|
@ -1249,22 +1268,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frozen) {
|
if (!frozen)
|
||||||
down_read(&policy->rwsem);
|
cpufreq_policy_put_kobj(policy);
|
||||||
kobj = &policy->kobj;
|
|
||||||
cmp = &policy->kobj_unregister;
|
|
||||||
up_read(&policy->rwsem);
|
|
||||||
kobject_put(kobj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to make sure that the underlying kobj is
|
|
||||||
* actually not referenced anymore by anybody before we
|
|
||||||
* proceed with unloading.
|
|
||||||
*/
|
|
||||||
pr_debug("waiting for dropping of refcount\n");
|
|
||||||
wait_for_completion(cmp);
|
|
||||||
pr_debug("wait complete\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the ->exit() even during light-weight tear-down,
|
* Perform the ->exit() even during light-weight tear-down,
|
||||||
|
|
|
@ -81,6 +81,7 @@ void pm_vt_switch_unregister(struct device *dev)
|
||||||
list_for_each_entry(tmp, &pm_vt_switch_list, head) {
|
list_for_each_entry(tmp, &pm_vt_switch_list, head) {
|
||||||
if (tmp->dev == dev) {
|
if (tmp->dev == dev) {
|
||||||
list_del(&tmp->head);
|
list_del(&tmp->head);
|
||||||
|
kfree(tmp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче