Date:2010-07-04 01:05:54 (13 years 8 months ago)
Author:Maarten ter Huurne
Commit:c3c4d206a978ca36f2d01fe58bb5e4c63fe4332c
Message:cpufreq_stats: Support runtime changes to frequency table.

Files: drivers/cpufreq/cpufreq_stats.c (10 diffs)

Change Details

drivers/cpufreq/cpufreq_stats.c
2020#include <linux/kobject.h>
2121#include <linux/spinlock.h>
2222#include <linux/notifier.h>
23#include <linux/string.h>
2324#include <asm/cputime.h>
2425
2526static spinlock_t cpufreq_stats_lock;
...... 
3637    unsigned long long last_time;
3738    unsigned int max_state;
3839    unsigned int state_num;
39    unsigned int last_index;
40    int last_index;
4041    cputime64_t *time_in_state;
4142    unsigned int *freq_table;
4243#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
...... 
5960    cur_time = get_jiffies_64();
6061    spin_lock(&cpufreq_stats_lock);
6162    stat = per_cpu(cpufreq_stats_table, cpu);
62    if (stat->time_in_state)
63    if (stat->time_in_state && stat->last_index != -1)
6364        stat->time_in_state[stat->last_index] =
6465            cputime64_add(stat->time_in_state[stat->last_index],
6566                      cputime_sub(cur_time, stat->last_time));
...... 
8283    ssize_t len = 0;
8384    int i;
8485    struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
85    if (!stat)
86    if (!stat || !stat->time_in_state)
8687        return 0;
8788    cpufreq_stats_update(stat->cpu);
8889    for (i = 0; i < stat->state_num; i++) {
...... 
100101    int i, j;
101102
102103    struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
103    if (!stat)
104    if (!stat || !stat->trans_table)
104105        return 0;
105106    cpufreq_stats_update(stat->cpu);
106107    len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
...... 
159160static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
160161{
161162    int index;
162    for (index = 0; index < stat->max_state; index++)
163        if (stat->freq_table[index] == freq)
164            return index;
163    if (stat->freq_table)
164        for (index = 0; index < stat->max_state; index++)
165            if (stat->freq_table[index] == freq)
166                return index;
165167    return -1;
166168}
167169
...... 
180182        cpufreq_cpu_put(policy);
181183}
182184
183static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
185static int cpufreq_stats_update_table(struct cpufreq_policy *policy,
184186        struct cpufreq_frequency_table *table)
185187{
186    unsigned int i, j, count = 0, ret = 0;
187    struct cpufreq_stats *stat;
188    struct cpufreq_policy *data;
188    unsigned int i, j, count = 0;
189189    unsigned int alloc_size;
190190    unsigned int cpu = policy->cpu;
191    if (per_cpu(cpufreq_stats_table, cpu))
192        return -EBUSY;
193    stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL);
194    if ((stat) == NULL)
195        return -ENOMEM;
196
197    data = cpufreq_cpu_get(cpu);
198    if (data == NULL) {
199        ret = -EINVAL;
200        goto error_get_fail;
201    }
202
203    ret = sysfs_create_group(&data->kobj, &stats_attr_group);
204    if (ret)
205        goto error_out;
206
207    stat->cpu = cpu;
208    per_cpu(cpufreq_stats_table, cpu) = stat;
191    struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
209192
210193    for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
211194        unsigned int freq = table[i].frequency;
...... 
214197        count++;
215198    }
216199
200    if (stat->max_state != count) {
201        stat->max_state = count;
202        kfree(stat->time_in_state);
203        stat->time_in_state = NULL;
204    }
217205    alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
218
219206#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
220207    alloc_size += count * count * sizeof(int);
221208#endif
222    stat->max_state = count;
223    stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
224    if (!stat->time_in_state) {
225        ret = -ENOMEM;
226        goto error_out;
227    }
228    stat->freq_table = (unsigned int *)(stat->time_in_state + count);
229
209    if (stat->time_in_state) {
210        memset(stat->time_in_state, 0, alloc_size);
211    } else {
212        stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
213        if (!stat->time_in_state)
214            return -ENOMEM;
215        stat->freq_table = (unsigned int *)(
216                stat->time_in_state + count);
230217#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
231    stat->trans_table = stat->freq_table + count;
218        stat->trans_table = stat->freq_table + count;
232219#endif
220    }
221
233222    j = 0;
234    for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
235        unsigned int freq = table[i].frequency;
236        if (freq == CPUFREQ_ENTRY_INVALID)
237            continue;
238        if (freq_table_get_index(stat, freq) == -1)
239            stat->freq_table[j++] = freq;
223    if (stat->freq_table) {
224        for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
225            unsigned int freq = table[i].frequency;
226            if (freq == CPUFREQ_ENTRY_INVALID)
227                continue;
228            if (freq_table_get_index(stat, freq) == -1)
229                stat->freq_table[j++] = freq;
230        }
240231    }
241232    stat->state_num = j;
242233    spin_lock(&cpufreq_stats_lock);
243234    stat->last_time = get_jiffies_64();
244235    stat->last_index = freq_table_get_index(stat, policy->cur);
245236    spin_unlock(&cpufreq_stats_lock);
237    return 0;
238}
239
240static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
241        struct cpufreq_frequency_table *table)
242{
243    unsigned int ret = 0;
244    struct cpufreq_stats *stat;
245    struct cpufreq_policy *data;
246    unsigned int cpu = policy->cpu;
247
248    stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL);
249    if ((stat) == NULL)
250        return -ENOMEM;
251
252    data = cpufreq_cpu_get(cpu);
253    if (data == NULL) {
254        ret = -EINVAL;
255        goto error_out;
256    }
257    ret = sysfs_create_group(&data->kobj, &stats_attr_group);
246258    cpufreq_cpu_put(data);
259    if (ret)
260        goto error_out;
261
262    stat->cpu = cpu;
263    per_cpu(cpufreq_stats_table, cpu) = stat;
264
247265    return 0;
248266error_out:
249    cpufreq_cpu_put(data);
250error_get_fail:
251267    kfree(stat);
252268    per_cpu(cpufreq_stats_table, cpu) = NULL;
253269    return ret;
...... 
265281    table = cpufreq_frequency_get_table(cpu);
266282    if (!table)
267283        return 0;
268    ret = cpufreq_stats_create_table(policy, table);
269    if (ret)
270        return ret;
271    return 0;
284    if (!per_cpu(cpufreq_stats_table, cpu)) {
285        ret = cpufreq_stats_create_table(policy, table);
286        if (ret)
287            return ret;
288    }
289    return cpufreq_stats_update_table(policy, table);
272290}
273291
274292static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
...... 
292310    if (old_index == new_index)
293311        return 0;
294312
295    if (old_index == -1 || new_index == -1)
313    if (new_index == -1)
296314        return 0;
297315
298316    spin_lock(&cpufreq_stats_lock);
299317    stat->last_index = new_index;
318    if (old_index != -1) {
300319#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
301    stat->trans_table[old_index * stat->max_state + new_index]++;
320        if (stat->trans_table)
321            stat->trans_table[old_index * stat->max_state +
322                      new_index]++;
302323#endif
303    stat->total_trans++;
324        stat->total_trans++;
325    }
304326    spin_unlock(&cpufreq_stats_lock);
305327    return 0;
306328}

Archive Download the corresponding diff file



interactive