aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/cpufreq.c40
-rw-r--r--drivers/cpufreq/freq_table.c22
-rw-r--r--include/linux/cpufreq.h2
3 files changed, 64 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d533c205eea4..3509ca04b5bb 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1073,6 +1073,46 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
1073 } 1073 }
1074 } 1074 }
1075 1075
1076 /*
1077 * Sometimes boot loaders set CPU frequency to a value outside of
1078 * frequency table present with cpufreq core. In such cases CPU might be
1079 * unstable if it has to run on that frequency for long duration of time
1080 * and so its better to set it to a frequency which is specified in
1081 * freq-table. This also makes cpufreq stats inconsistent as
1082 * cpufreq-stats would fail to register because current frequency of CPU
1083 * isn't found in freq-table.
1084 *
1085 * Because we don't want this change to effect boot process badly, we go
1086 * for the next freq which is >= policy->cur ('cur' must be set by now,
1087 * otherwise we will end up setting freq to lowest of the table as 'cur'
1088 * is initialized to zero).
1089 *
1090 * We are passing target-freq as "policy->cur - 1" otherwise
1091 * __cpufreq_driver_target() would simply fail, as policy->cur will be
1092 * equal to target-freq.
1093 */
1094 if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
1095 && has_target()) {
1096 /* Are we running at unknown frequency ? */
1097 ret = cpufreq_frequency_table_get_index(policy, policy->cur);
1098 if (ret == -EINVAL) {
1099 /* Warn user and fix it */
1100 pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n",
1101 __func__, policy->cpu, policy->cur);
1102 ret = __cpufreq_driver_target(policy, policy->cur - 1,
1103 CPUFREQ_RELATION_L);
1104
1105 /*
1106 * Reaching here after boot in a few seconds may not
1107 * mean that system will remain stable at "unknown"
1108 * frequency for longer duration. Hence, a BUG_ON().
1109 */
1110 BUG_ON(ret);
1111 pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n",
1112 __func__, policy->cpu, policy->cur);
1113 }
1114 }
1115
1076 /* related cpus should atleast have policy->cpus */ 1116 /* related cpus should atleast have policy->cpus */
1077 cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); 1117 cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
1078 1118
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 3458d27f63b4..a8ac0427fbfe 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -178,7 +178,29 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
178} 178}
179EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); 179EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
180 180
181int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
182 unsigned int freq)
183{
184 struct cpufreq_frequency_table *table;
185 int i;
186
187 table = cpufreq_frequency_get_table(policy->cpu);
188 if (unlikely(!table)) {
189 pr_debug("%s: Unable to find frequency table\n", __func__);
190 return -ENOENT;
191 }
192
193 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
194 if (table[i].frequency == freq)
195 return i;
196 }
197
198 return -EINVAL;
199}
200EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
201
181static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); 202static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
203
182/** 204/**
183 * show_available_freqs - show available frequencies for the specified CPU 205 * show_available_freqs - show available frequencies for the specified CPU
184 */ 206 */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 91b8c84e8cd0..aaf800eb9dd2 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -450,6 +450,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
450 unsigned int target_freq, 450 unsigned int target_freq,
451 unsigned int relation, 451 unsigned int relation,
452 unsigned int *index); 452 unsigned int *index);
453int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
454 unsigned int freq);
453 455
454void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); 456void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
455ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); 457ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);