aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-12 07:04:11 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-12 07:04:11 -0400
commitf1728fd1599112239ed5cebc7be9810264db6792 (patch)
treede36bb207a71db98c7170b57c557017e340831b7
parent0df03a30c333d67ee9b4c37f32d423624f48fe05 (diff)
parent44871c9c7f7963f8869dd8bc9620221c9e9db153 (diff)
Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: Acquire the lock in cpufreq_policy_restore() for reading cpufreq: Prevent problems in update_policy_cpu() if last_cpu == new_cpu cpufreq: Restructure if/else block to avoid unintended behavior cpufreq: Fix crash in cpufreq-stats during suspend/resume
-rw-r--r--drivers/cpufreq/cpufreq.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 5a64f66d36e0..43c24aa756f6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -906,11 +906,11 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
906 struct cpufreq_policy *policy; 906 struct cpufreq_policy *policy;
907 unsigned long flags; 907 unsigned long flags;
908 908
909 write_lock_irqsave(&cpufreq_driver_lock, flags); 909 read_lock_irqsave(&cpufreq_driver_lock, flags);
910 910
911 policy = per_cpu(cpufreq_cpu_data_fallback, cpu); 911 policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
912 912
913 write_unlock_irqrestore(&cpufreq_driver_lock, flags); 913 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
914 914
915 return policy; 915 return policy;
916} 916}
@@ -947,6 +947,21 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
947 kfree(policy); 947 kfree(policy);
948} 948}
949 949
950static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
951{
952 if (cpu == policy->cpu)
953 return;
954
955 policy->last_cpu = policy->cpu;
956 policy->cpu = cpu;
957
958#ifdef CONFIG_CPU_FREQ_TABLE
959 cpufreq_frequency_table_update_policy_cpu(policy);
960#endif
961 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
962 CPUFREQ_UPDATE_POLICY_CPU, policy);
963}
964
950static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, 965static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
951 bool frozen) 966 bool frozen)
952{ 967{
@@ -1000,7 +1015,18 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
1000 if (!policy) 1015 if (!policy)
1001 goto nomem_out; 1016 goto nomem_out;
1002 1017
1003 policy->cpu = cpu; 1018
1019 /*
1020 * In the resume path, since we restore a saved policy, the assignment
1021 * to policy->cpu is like an update of the existing policy, rather than
1022 * the creation of a brand new one. So we need to perform this update
1023 * by invoking update_policy_cpu().
1024 */
1025 if (frozen && cpu != policy->cpu)
1026 update_policy_cpu(policy, cpu);
1027 else
1028 policy->cpu = cpu;
1029
1004 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 1030 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
1005 cpumask_copy(policy->cpus, cpumask_of(cpu)); 1031 cpumask_copy(policy->cpus, cpumask_of(cpu));
1006 1032
@@ -1092,18 +1118,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1092 return __cpufreq_add_dev(dev, sif, false); 1118 return __cpufreq_add_dev(dev, sif, false);
1093} 1119}
1094 1120
1095static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
1096{
1097 policy->last_cpu = policy->cpu;
1098 policy->cpu = cpu;
1099
1100#ifdef CONFIG_CPU_FREQ_TABLE
1101 cpufreq_frequency_table_update_policy_cpu(policy);
1102#endif
1103 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1104 CPUFREQ_UPDATE_POLICY_CPU, policy);
1105}
1106
1107static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, 1121static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1108 unsigned int old_cpu, bool frozen) 1122 unsigned int old_cpu, bool frozen)
1109{ 1123{
@@ -1182,8 +1196,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
1182 cpumask_clear_cpu(cpu, policy->cpus); 1196 cpumask_clear_cpu(cpu, policy->cpus);
1183 unlock_policy_rwsem_write(cpu); 1197 unlock_policy_rwsem_write(cpu);
1184 1198
1185 if (cpu != policy->cpu && !frozen) { 1199 if (cpu != policy->cpu) {
1186 sysfs_remove_link(&dev->kobj, "cpufreq"); 1200 if (!frozen)
1201 sysfs_remove_link(&dev->kobj, "cpufreq");
1187 } else if (cpus > 1) { 1202 } else if (cpus > 1) {
1188 1203
1189 new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen); 1204 new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);