Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 42f921a

Browse files
vireshkrafaeljw
authored andcommitted
cpufreq: remove sysfs files for CPUs which failed to come back after resume
There are cases where cpufreq_add_dev() may fail for some CPUs during system resume. With the current code we will still have sysfs cpufreq files for those CPUs and struct cpufreq_policy would be already freed for them. Hence any operation on those sysfs files would result in kernel warnings. Example of problems resulting from resume errors (from Bjørn Mork): WARNING: CPU: 0 PID: 6055 at fs/sysfs/file.c:343 sysfs_open_file+0x77/0x212() missing sysfs attribute operations for kobject: (null) Modules linked in: [stripped as irrelevant] CPU: 0 PID: 6055 Comm: grep Tainted: G D 3.13.0-rc2 torvalds#153 Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 12/19/2011 0000000000000009 ffff8802327ebb78 ffffffff81380b0e 0000000000000006 ffff8802327ebbc8 ffff8802327ebbb8 ffffffff81038635 0000000000000000 ffffffff811823c7 ffff88021a19e688 ffff88021a19e688 ffff8802302f9310 Call Trace: [<ffffffff81380b0e>] dump_stack+0x55/0x76 [<ffffffff81038635>] warn_slowpath_common+0x7c/0x96 [<ffffffff811823c7>] ? sysfs_open_file+0x77/0x212 [<ffffffff810386e3>] warn_slowpath_fmt+0x41/0x43 [<ffffffff81182dec>] ? sysfs_get_active+0x6b/0x82 [<ffffffff81182382>] ? sysfs_open_file+0x32/0x212 [<ffffffff811823c7>] sysfs_open_file+0x77/0x212 [<ffffffff81182350>] ? sysfs_schedule_callback+0x1ac/0x1ac [<ffffffff81122562>] do_dentry_open+0x17c/0x257 [<ffffffff8112267e>] finish_open+0x41/0x4f [<ffffffff81130225>] do_last+0x80c/0x9ba [<ffffffff8112dbbd>] ? inode_permission+0x40/0x42 [<ffffffff81130606>] path_openat+0x233/0x4a1 [<ffffffff81130b7e>] do_filp_open+0x35/0x85 [<ffffffff8113b787>] ? __alloc_fd+0x172/0x184 [<ffffffff811232ea>] do_sys_open+0x6b/0xfa [<ffffffff811233a7>] SyS_openat+0xf/0x11 [<ffffffff8138c812>] system_call_fastpath+0x16/0x1b To fix this, remove those sysfs files or put the associated kobject in case of such errors. Also, to make it simple, remove the cpufreq sysfs links from all the CPUs (except for the policy->cpu) during suspend, as that operation won't result in a loss of sysfs file permissions and we can create those links during resume just fine. Fixes: 5302c3f ("cpufreq: Perform light-weight init/teardown during suspend/resume") Reported-and-tested-by: Bjørn Mork <[email protected]> Signed-off-by: Viresh Kumar <[email protected]> Cc: 3.12+ <[email protected]> # 3.12+ [rjw: Changelog] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 319e2e3 commit 42f921a

File tree

1 file changed

+31
-32
lines changed

1 file changed

+31
-32
lines changed

drivers/cpufreq/cpufreq.c

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
845845

846846
#ifdef CONFIG_HOTPLUG_CPU
847847
static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
848-
unsigned int cpu, struct device *dev,
849-
bool frozen)
848+
unsigned int cpu, struct device *dev)
850849
{
851850
int ret = 0;
852851
unsigned long flags;
@@ -877,11 +876,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
877876
}
878877
}
879878

880-
/* Don't touch sysfs links during light-weight init */
881-
if (!frozen)
882-
ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
883-
884-
return ret;
879+
return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
885880
}
886881
#endif
887882

@@ -926,6 +921,27 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void)
926921
return NULL;
927922
}
928923

924+
static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
925+
{
926+
struct kobject *kobj;
927+
struct completion *cmp;
928+
929+
down_read(&policy->rwsem);
930+
kobj = &policy->kobj;
931+
cmp = &policy->kobj_unregister;
932+
up_read(&policy->rwsem);
933+
kobject_put(kobj);
934+
935+
/*
936+
* We need to make sure that the underlying kobj is
937+
* actually not referenced anymore by anybody before we
938+
* proceed with unloading.
939+
*/
940+
pr_debug("waiting for dropping of refcount\n");
941+
wait_for_completion(cmp);
942+
pr_debug("wait complete\n");
943+
}
944+
929945
static void cpufreq_policy_free(struct cpufreq_policy *policy)
930946
{
931947
free_cpumask_var(policy->related_cpus);
@@ -986,7 +1002,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
9861002
list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
9871003
if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
9881004
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
989-
ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
1005+
ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
9901006
up_read(&cpufreq_rwsem);
9911007
return ret;
9921008
}
@@ -1096,7 +1112,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
10961112
if (cpufreq_driver->exit)
10971113
cpufreq_driver->exit(policy);
10981114
err_set_policy_cpu:
1115+
if (frozen)
1116+
cpufreq_policy_put_kobj(policy);
10991117
cpufreq_policy_free(policy);
1118+
11001119
nomem_out:
11011120
up_read(&cpufreq_rwsem);
11021121

@@ -1118,18 +1137,14 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
11181137
}
11191138

11201139
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1121-
unsigned int old_cpu, bool frozen)
1140+
unsigned int old_cpu)
11221141
{
11231142
struct device *cpu_dev;
11241143
int ret;
11251144

11261145
/* first sibling now owns the new sysfs dir */
11271146
cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
11281147

1129-
/* Don't touch sysfs files during light-weight tear-down */
1130-
if (frozen)
1131-
return cpu_dev->id;
1132-
11331148
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
11341149
ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
11351150
if (ret) {
@@ -1196,7 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
11961211
if (!frozen)
11971212
sysfs_remove_link(&dev->kobj, "cpufreq");
11981213
} else if (cpus > 1) {
1199-
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
1214+
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
12001215
if (new_cpu >= 0) {
12011216
update_policy_cpu(policy, new_cpu);
12021217

@@ -1218,8 +1233,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
12181233
int ret;
12191234
unsigned long flags;
12201235
struct cpufreq_policy *policy;
1221-
struct kobject *kobj;
1222-
struct completion *cmp;
12231236

12241237
read_lock_irqsave(&cpufreq_driver_lock, flags);
12251238
policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1262,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
12491262
}
12501263
}
12511264

1252-
if (!frozen) {
1253-
down_read(&policy->rwsem);
1254-
kobj = &policy->kobj;
1255-
cmp = &policy->kobj_unregister;
1256-
up_read(&policy->rwsem);
1257-
kobject_put(kobj);
1258-
1259-
/*
1260-
* We need to make sure that the underlying kobj is
1261-
* actually not referenced anymore by anybody before we
1262-
* proceed with unloading.
1263-
*/
1264-
pr_debug("waiting for dropping of refcount\n");
1265-
wait_for_completion(cmp);
1266-
pr_debug("wait complete\n");
1267-
}
1265+
if (!frozen)
1266+
cpufreq_policy_put_kobj(policy);
12681267

12691268
/*
12701269
* Perform the ->exit() even during light-weight tear-down,

0 commit comments

Comments
 (0)