aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-12-20 10:56:02 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-12-21 18:47:46 -0500
commit42f921a6f10c6c2079b093a115eb7e3c3508357f (patch)
tree2dd7201d07f78e558ee3384afee510927a4a7f58 /drivers/cpufreq
parent319e2e3f63c348a9b66db4667efa73178e18b17d (diff)
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 #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: 5302c3fb2e62 ("cpufreq: Perform light-weight init/teardown during suspend/resume") Reported-and-tested-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: 3.12+ <stable@vger.kernel.org> # 3.12+ [rjw: Changelog] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 02d534da22dd..fab042e1ee90 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -845,8 +845,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
845 845
846#ifdef CONFIG_HOTPLUG_CPU 846#ifdef CONFIG_HOTPLUG_CPU
847static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, 847static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
848 unsigned int cpu, struct device *dev, 848 unsigned int cpu, struct device *dev)
849 bool frozen)
850{ 849{
851 int ret = 0; 850 int ret = 0;
852 unsigned long flags; 851 unsigned long flags;
@@ -877,11 +876,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
877 } 876 }
878 } 877 }
879 878
880 /* Don't touch sysfs links during light-weight init */ 879 return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
881 if (!frozen)
882 ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
883
884 return ret;
885} 880}
886#endif 881#endif
887 882
@@ -926,6 +921,27 @@ err_free_policy:
926 return NULL; 921 return NULL;
927} 922}
928 923
924static 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
929static void cpufreq_policy_free(struct cpufreq_policy *policy) 945static void cpufreq_policy_free(struct cpufreq_policy *policy)
930{ 946{
931 free_cpumask_var(policy->related_cpus); 947 free_cpumask_var(policy->related_cpus);
@@ -986,7 +1002,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
986 list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { 1002 list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
987 if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { 1003 if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
988 read_unlock_irqrestore(&cpufreq_driver_lock, flags); 1004 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);
990 up_read(&cpufreq_rwsem); 1006 up_read(&cpufreq_rwsem);
991 return ret; 1007 return ret;
992 } 1008 }
@@ -1096,7 +1112,10 @@ err_get_freq:
1096 if (cpufreq_driver->exit) 1112 if (cpufreq_driver->exit)
1097 cpufreq_driver->exit(policy); 1113 cpufreq_driver->exit(policy);
1098err_set_policy_cpu: 1114err_set_policy_cpu:
1115 if (frozen)
1116 cpufreq_policy_put_kobj(policy);
1099 cpufreq_policy_free(policy); 1117 cpufreq_policy_free(policy);
1118
1100nomem_out: 1119nomem_out:
1101 up_read(&cpufreq_rwsem); 1120 up_read(&cpufreq_rwsem);
1102 1121
@@ -1118,7 +1137,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1118} 1137}
1119 1138
1120static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, 1139static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1121 unsigned int old_cpu, bool frozen) 1140 unsigned int old_cpu)
1122{ 1141{
1123 struct device *cpu_dev; 1142 struct device *cpu_dev;
1124 int ret; 1143 int ret;
@@ -1126,10 +1145,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1126 /* first sibling now owns the new sysfs dir */ 1145 /* first sibling now owns the new sysfs dir */
1127 cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu)); 1146 cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
1128 1147
1129 /* Don't touch sysfs files during light-weight tear-down */
1130 if (frozen)
1131 return cpu_dev->id;
1132
1133 sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); 1148 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1134 ret = kobject_move(&policy->kobj, &cpu_dev->kobj); 1149 ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
1135 if (ret) { 1150 if (ret) {
@@ -1196,7 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
1196 if (!frozen) 1211 if (!frozen)
1197 sysfs_remove_link(&dev->kobj, "cpufreq"); 1212 sysfs_remove_link(&dev->kobj, "cpufreq");
1198 } else if (cpus > 1) { 1213 } 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);
1200 if (new_cpu >= 0) { 1215 if (new_cpu >= 0) {
1201 update_policy_cpu(policy, new_cpu); 1216 update_policy_cpu(policy, new_cpu);
1202 1217
@@ -1218,8 +1233,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
1218 int ret; 1233 int ret;
1219 unsigned long flags; 1234 unsigned long flags;
1220 struct cpufreq_policy *policy; 1235 struct cpufreq_policy *policy;
1221 struct kobject *kobj;
1222 struct completion *cmp;
1223 1236
1224 read_lock_irqsave(&cpufreq_driver_lock, flags); 1237 read_lock_irqsave(&cpufreq_driver_lock, flags);
1225 policy = per_cpu(cpufreq_cpu_data, cpu); 1238 policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1262,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
1249 } 1262 }
1250 } 1263 }
1251 1264
1252 if (!frozen) { 1265 if (!frozen)
1253 down_read(&policy->rwsem); 1266 cpufreq_policy_put_kobj(policy);
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 }
1268 1267
1269 /* 1268 /*
1270 * Perform the ->exit() even during light-weight tear-down, 1269 * Perform the ->exit() even during light-weight tear-down,