summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_stats.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index c315ec9d5686..c136b787c5af 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -59,7 +59,7 @@ static int cpufreq_stats_update(unsigned int cpu)
cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
stat = per_cpu(cpufreq_stats_table, cpu);
- if (stat->time_in_state)
+ if (stat->time_in_state && stat->last_index >= 0)
stat->time_in_state[stat->last_index] =
cputime64_add(stat->time_in_state[stat->last_index],
cputime_sub(cur_time, stat->last_time));
@@ -159,10 +159,10 @@ static struct attribute_group stats_attr_group = {
static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
{
int index;
- for (index = 0; index < stat->max_state; index++)
- if (stat->freq_table[index] == freq)
- return index;
- return -1;
+ for (index = 0; index < stat->state_num; index++)
+ if (stat->freq_table[index] > freq)
+ break;
+ return index - 1; /* below lowest freq in table: return -1 */
}
/* should be called late in the CPU removal sequence so that the stats
@@ -193,7 +193,7 @@ static void cpufreq_stats_free_sysfs(unsigned int cpu)
static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
- unsigned int i, j, count = 0, ret = 0;
+ unsigned int i, j, k, l, count = 0, ret = 0;
struct cpufreq_stats *stat;
struct cpufreq_policy *data;
unsigned int alloc_size;
@@ -245,8 +245,16 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
- if (freq_table_get_index(stat, freq) == -1)
- stat->freq_table[j++] = freq;
+
+ /* Insert in sorted stat->freq_table */
+ for (k = 0; k < j && stat->freq_table[k] < freq; k++)
+ ;
+ if (stat->freq_table[k] == freq)
+ continue;
+ for (l = j; l > k; l--)
+ stat->freq_table[l] = stat->freq_table[l - 1];
+ stat->freq_table[k] = freq;
+ j++;
}
stat->state_num = j;
spin_lock(&cpufreq_stats_lock);
@@ -298,10 +306,6 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
old_index = stat->last_index;
new_index = freq_table_get_index(stat, freq->new);
- /* We can't do stat->time_in_state[-1]= .. */
- if (old_index == -1 || new_index == -1)
- return 0;
-
cpufreq_stats_update(freq->cpu);
if (old_index == new_index)
@@ -310,7 +314,8 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
spin_lock(&cpufreq_stats_lock);
stat->last_index = new_index;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
- stat->trans_table[old_index * stat->max_state + new_index]++;
+ if (old_index >= 0 && new_index >= 0)
+ stat->trans_table[old_index * stat->max_state + new_index]++;
#endif
stat->total_trans++;
spin_unlock(&cpufreq_stats_lock);