blob: 5e370a30a964f5f30e9944daa9a768507c938af4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/cpufreq/cpufreq_stats.c
3 *
4 * Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
Dave Jones0a829c52009-01-18 01:49:04 -05005 * (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/cpu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/cpufreq.h>
Paul Gortmaker5c720d372011-05-27 13:23:32 -040014#include <linux/module.h>
Viresh Kumar5ff0a262013-08-06 22:53:03 +053015#include <linux/slab.h>
Frederic Weisbeckerbfc3f022014-03-05 16:33:42 +010016#include <linux/cputime.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017
18static spinlock_t cpufreq_stats_lock;
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020struct cpufreq_stats {
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 unsigned int total_trans;
Viresh Kumarbb176f72013-06-19 14:19:33 +053022 unsigned long long last_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 unsigned int max_state;
24 unsigned int state_num;
25 unsigned int last_index;
Viresh Kumar1e7586a2012-10-26 00:51:21 +020026 u64 *time_in_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 unsigned int *freq_table;
28#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
29 unsigned int *trans_table;
30#endif
31};
32
Viresh Kumar50941602015-01-06 21:09:07 +053033static int cpufreq_stats_update(struct cpufreq_stats *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -070034{
Viresh Kumar95313472015-01-06 21:09:03 +053035 unsigned long long cur_time = get_jiffies_64();
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070036
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 spin_lock(&cpufreq_stats_lock);
Viresh Kumarc960f9b2015-01-06 21:09:12 +053038 stats->time_in_state[stats->last_index] += cur_time - stats->last_time;
Viresh Kumar50941602015-01-06 21:09:07 +053039 stats->last_time = cur_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 spin_unlock(&cpufreq_stats_lock);
41 return 0;
42}
43
Dave Jones0a829c52009-01-18 01:49:04 -050044static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045{
Viresh Kumara9aaf292015-01-13 11:34:00 +053046 return sprintf(buf, "%d\n", policy->stats->total_trans);
Linus Torvalds1da177e2005-04-16 15:20:36 -070047}
48
Dave Jones0a829c52009-01-18 01:49:04 -050049static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
Viresh Kumar50941602015-01-06 21:09:07 +053051 struct cpufreq_stats *stats = policy->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 ssize_t len = 0;
53 int i;
Viresh Kumara9aaf292015-01-13 11:34:00 +053054
Viresh Kumar50941602015-01-06 21:09:07 +053055 cpufreq_stats_update(stats);
56 for (i = 0; i < stats->state_num; i++) {
57 len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i],
Dave Jones0a829c52009-01-18 01:49:04 -050058 (unsigned long long)
Viresh Kumar50941602015-01-06 21:09:07 +053059 jiffies_64_to_clock_t(stats->time_in_state[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 }
61 return len;
62}
63
64#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
Dave Jones0a829c52009-01-18 01:49:04 -050065static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
Viresh Kumar50941602015-01-06 21:09:07 +053067 struct cpufreq_stats *stats = policy->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 ssize_t len = 0;
69 int i, j;
70
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070071 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
72 len += snprintf(buf + len, PAGE_SIZE - len, " : ");
Viresh Kumar50941602015-01-06 21:09:07 +053073 for (i = 0; i < stats->state_num; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 if (len >= PAGE_SIZE)
75 break;
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070076 len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
Viresh Kumar50941602015-01-06 21:09:07 +053077 stats->freq_table[i]);
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070078 }
79 if (len >= PAGE_SIZE)
Cesar Eduardo Barros25aca342008-02-16 08:41:25 -020080 return PAGE_SIZE;
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070081
82 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
83
Viresh Kumar50941602015-01-06 21:09:07 +053084 for (i = 0; i < stats->state_num; i++) {
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070085 if (len >= PAGE_SIZE)
86 break;
87
88 len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ",
Viresh Kumar50941602015-01-06 21:09:07 +053089 stats->freq_table[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
Viresh Kumar50941602015-01-06 21:09:07 +053091 for (j = 0; j < stats->state_num; j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 if (len >= PAGE_SIZE)
93 break;
Venkatesh Pallipadi58f1df22005-05-25 14:46:50 -070094 len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
Viresh Kumar50941602015-01-06 21:09:07 +053095 stats->trans_table[i*stats->max_state+j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 }
Cesar Eduardo Barros25aca342008-02-16 08:41:25 -020097 if (len >= PAGE_SIZE)
98 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
100 }
Cesar Eduardo Barros25aca342008-02-16 08:41:25 -0200101 if (len >= PAGE_SIZE)
102 return PAGE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 return len;
104}
Viresh Kumardf18e502013-02-04 11:38:52 +0000105cpufreq_freq_attr_ro(trans_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106#endif
107
Viresh Kumardf18e502013-02-04 11:38:52 +0000108cpufreq_freq_attr_ro(total_trans);
109cpufreq_freq_attr_ro(time_in_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111static struct attribute *default_attrs[] = {
Viresh Kumardf18e502013-02-04 11:38:52 +0000112 &total_trans.attr,
113 &time_in_state.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
Viresh Kumardf18e502013-02-04 11:38:52 +0000115 &trans_table.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116#endif
117 NULL
118};
119static struct attribute_group stats_attr_group = {
120 .attrs = default_attrs,
121 .name = "stats"
122};
123
Viresh Kumar50941602015-01-06 21:09:07 +0530124static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
126 int index;
Viresh Kumar50941602015-01-06 21:09:07 +0530127 for (index = 0; index < stats->max_state; index++)
128 if (stats->freq_table[index] == freq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 return index;
130 return -1;
131}
132
Viresh Kumar2d135942014-01-07 07:10:12 +0530133static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134{
Viresh Kumar50941602015-01-06 21:09:07 +0530135 struct cpufreq_stats *stats = policy->stats;
Viresh Kumarb8eed8a2013-01-14 13:23:03 +0000136
Viresh Kumara9aaf292015-01-13 11:34:00 +0530137 /* Already freed */
Viresh Kumar50941602015-01-06 21:09:07 +0530138 if (!stats)
Viresh Kumar2d135942014-01-07 07:10:12 +0530139 return;
140
Viresh Kumar50941602015-01-06 21:09:07 +0530141 pr_debug("%s: Free stats table\n", __func__);
Viresh Kumar2d135942014-01-07 07:10:12 +0530142
143 sysfs_remove_group(&policy->kobj, &stats_attr_group);
Viresh Kumar50941602015-01-06 21:09:07 +0530144 kfree(stats->time_in_state);
145 kfree(stats);
Viresh Kumara9aaf292015-01-13 11:34:00 +0530146 policy->stats = NULL;
steven finney98586ed2011-05-02 11:29:17 -0700147}
148
Viresh Kumar2d135942014-01-07 07:10:12 +0530149static void cpufreq_stats_free_table(unsigned int cpu)
steven finney98586ed2011-05-02 11:29:17 -0700150{
Viresh Kumar2d135942014-01-07 07:10:12 +0530151 struct cpufreq_policy *policy;
Dirk Brandewie633d47d2013-02-06 09:02:12 -0800152
Viresh Kumar2d135942014-01-07 07:10:12 +0530153 policy = cpufreq_cpu_get(cpu);
viresh kumar187da1d2013-03-22 10:13:52 +0000154 if (!policy)
Dirk Brandewie633d47d2013-02-06 09:02:12 -0800155 return;
156
Viresh Kumarf93dbbb2015-01-06 21:09:04 +0530157 __cpufreq_stats_free_table(policy);
viresh kumar187da1d2013-03-22 10:13:52 +0000158
viresh kumar187da1d2013-03-22 10:13:52 +0000159 cpufreq_cpu_put(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160}
161
Saravana Kannanad4c2302014-02-27 17:58:36 -0800162static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163{
Viresh Kumara685c6d2015-01-06 21:09:11 +0530164 unsigned int i = 0, count = 0, ret = -ENOMEM;
Viresh Kumar50941602015-01-06 21:09:07 +0530165 struct cpufreq_stats *stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 unsigned int alloc_size;
167 unsigned int cpu = policy->cpu;
Stratos Karafotis041526f2014-04-25 23:15:38 +0300168 struct cpufreq_frequency_table *pos, *table;
Saravana Kannanad4c2302014-02-27 17:58:36 -0800169
Viresh Kumara685c6d2015-01-06 21:09:11 +0530170 /* We need cpufreq table for creating stats table */
Saravana Kannanad4c2302014-02-27 17:58:36 -0800171 table = cpufreq_frequency_get_table(cpu);
172 if (unlikely(!table))
173 return 0;
174
Viresh Kumarb8c67442015-01-06 21:09:01 +0530175 /* stats already initialized */
Viresh Kumara9aaf292015-01-13 11:34:00 +0530176 if (policy->stats)
Viresh Kumarb8c67442015-01-06 21:09:01 +0530177 return -EEXIST;
178
Viresh Kumar50941602015-01-06 21:09:07 +0530179 stats = kzalloc(sizeof(*stats), GFP_KERNEL);
Viresh Kumara685c6d2015-01-06 21:09:11 +0530180 if (!stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Viresh Kumara685c6d2015-01-06 21:09:11 +0530183 /* Find total allocation size */
Stratos Karafotis041526f2014-04-25 23:15:38 +0300184 cpufreq_for_each_valid_entry(pos, table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
Viresh Kumar1e7586a2012-10-26 00:51:21 +0200187 alloc_size = count * sizeof(int) + count * sizeof(u64);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
189#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
190 alloc_size += count * count * sizeof(int);
191#endif
Viresh Kumara685c6d2015-01-06 21:09:11 +0530192
193 /* Allocate memory for time_in_state/freq_table/trans_table in one go */
Viresh Kumar50941602015-01-06 21:09:07 +0530194 stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
Viresh Kumara685c6d2015-01-06 21:09:11 +0530195 if (!stats->time_in_state)
196 goto free_stat;
197
Viresh Kumar50941602015-01-06 21:09:07 +0530198 stats->freq_table = (unsigned int *)(stats->time_in_state + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
Viresh Kumar50941602015-01-06 21:09:07 +0530201 stats->trans_table = stats->freq_table + count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#endif
Viresh Kumara685c6d2015-01-06 21:09:11 +0530203
204 stats->max_state = count;
205
206 /* Find valid-unique entries */
Stratos Karafotis041526f2014-04-25 23:15:38 +0300207 cpufreq_for_each_valid_entry(pos, table)
Viresh Kumar50941602015-01-06 21:09:07 +0530208 if (freq_table_get_index(stats, pos->frequency) == -1)
209 stats->freq_table[i++] = pos->frequency;
Viresh Kumara685c6d2015-01-06 21:09:11 +0530210
Viresh Kumar490285c2015-01-06 21:09:15 +0530211 stats->state_num = i;
Viresh Kumar50941602015-01-06 21:09:07 +0530212 stats->last_time = get_jiffies_64();
213 stats->last_index = freq_table_get_index(stats, policy->cur);
Viresh Kumara685c6d2015-01-06 21:09:11 +0530214
215 policy->stats = stats;
216 ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
217 if (!ret)
218 return 0;
219
220 /* We failed, release resources */
Viresh Kumara9aaf292015-01-13 11:34:00 +0530221 policy->stats = NULL;
Viresh Kumara685c6d2015-01-06 21:09:11 +0530222 kfree(stats->time_in_state);
223free_stat:
224 kfree(stats);
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 return ret;
227}
228
Viresh Kumarb3f9ff82014-01-07 07:10:13 +0530229static void cpufreq_stats_create_table(unsigned int cpu)
230{
231 struct cpufreq_policy *policy;
Viresh Kumarb3f9ff82014-01-07 07:10:13 +0530232
233 /*
234 * "likely(!policy)" because normally cpufreq_stats will be registered
235 * before cpufreq driver
236 */
237 policy = cpufreq_cpu_get(cpu);
238 if (likely(!policy))
239 return;
240
Saravana Kannanad4c2302014-02-27 17:58:36 -0800241 __cpufreq_stats_create_table(policy);
Viresh Kumarb3f9ff82014-01-07 07:10:13 +0530242
243 cpufreq_cpu_put(policy);
244}
245
Dave Jones0a829c52009-01-18 01:49:04 -0500246static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
247 unsigned long val, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
Viresh Kumarfcd7af92014-01-07 07:10:10 +0530249 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 struct cpufreq_policy *policy = data;
Viresh Kumarb8eed8a2013-01-14 13:23:03 +0000251
Viresh Kumarfcd7af92014-01-07 07:10:10 +0530252 if (val == CPUFREQ_CREATE_POLICY)
Saravana Kannanad4c2302014-02-27 17:58:36 -0800253 ret = __cpufreq_stats_create_table(policy);
Viresh Kumar2d135942014-01-07 07:10:12 +0530254 else if (val == CPUFREQ_REMOVE_POLICY)
255 __cpufreq_stats_free_table(policy);
Viresh Kumarfcd7af92014-01-07 07:10:10 +0530256
257 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258}
259
Dave Jones0a829c52009-01-18 01:49:04 -0500260static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
261 unsigned long val, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262{
263 struct cpufreq_freqs *freq = data;
Viresh Kumara9aaf292015-01-13 11:34:00 +0530264 struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu);
Viresh Kumar50941602015-01-06 21:09:07 +0530265 struct cpufreq_stats *stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 int old_index, new_index;
267
Viresh Kumara9aaf292015-01-13 11:34:00 +0530268 if (!policy) {
269 pr_err("%s: No policy found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 return 0;
Viresh Kumara9aaf292015-01-13 11:34:00 +0530271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Viresh Kumara9aaf292015-01-13 11:34:00 +0530273 if (val != CPUFREQ_POSTCHANGE)
274 goto put_policy;
275
276 if (!policy->stats) {
277 pr_debug("%s: No stats found\n", __func__);
278 goto put_policy;
279 }
280
Viresh Kumar50941602015-01-06 21:09:07 +0530281 stats = policy->stats;
Venkatesh Pallipadi8edc59d92006-12-19 12:58:55 -0800282
Viresh Kumar50941602015-01-06 21:09:07 +0530283 old_index = stats->last_index;
284 new_index = freq_table_get_index(stats, freq->new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Viresh Kumar50941602015-01-06 21:09:07 +0530286 /* We can't do stats->time_in_state[-1]= .. */
Konrad Rzeszutek Wilk46a310b2011-06-16 15:36:38 -0400287 if (old_index == -1 || new_index == -1)
Viresh Kumara9aaf292015-01-13 11:34:00 +0530288 goto put_policy;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Konrad Rzeszutek Wilk46a310b2011-06-16 15:36:38 -0400290 if (old_index == new_index)
Viresh Kumara9aaf292015-01-13 11:34:00 +0530291 goto put_policy;
Venkatesh Pallipadi8edc59d92006-12-19 12:58:55 -0800292
Viresh Kumare7347692015-01-06 21:09:14 +0530293 cpufreq_stats_update(stats);
294
Viresh Kumar50941602015-01-06 21:09:07 +0530295 stats->last_index = new_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
Viresh Kumar50941602015-01-06 21:09:07 +0530297 stats->trans_table[old_index * stats->max_state + new_index]++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298#endif
Viresh Kumar50941602015-01-06 21:09:07 +0530299 stats->total_trans++;
Viresh Kumara9aaf292015-01-13 11:34:00 +0530300
301put_policy:
302 cpufreq_cpu_put(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 return 0;
304}
305
306static struct notifier_block notifier_policy_block = {
307 .notifier_call = cpufreq_stat_notifier_policy
308};
309
310static struct notifier_block notifier_trans_block = {
311 .notifier_call = cpufreq_stat_notifier_trans
312};
313
Dave Jones0a829c52009-01-18 01:49:04 -0500314static int __init cpufreq_stats_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
316 int ret;
317 unsigned int cpu;
Ashok Rajc32b6b82005-10-30 14:59:54 -0800318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 spin_lock_init(&cpufreq_stats_lock);
Dave Jones0a829c52009-01-18 01:49:04 -0500320 ret = cpufreq_register_notifier(&notifier_policy_block,
321 CPUFREQ_POLICY_NOTIFIER);
322 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 return ret;
324
Viresh Kumarb3f9ff82014-01-07 07:10:13 +0530325 for_each_online_cpu(cpu)
326 cpufreq_stats_create_table(cpu);
327
Dave Jones0a829c52009-01-18 01:49:04 -0500328 ret = cpufreq_register_notifier(&notifier_trans_block,
329 CPUFREQ_TRANSITION_NOTIFIER);
330 if (ret) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 cpufreq_unregister_notifier(&notifier_policy_block,
332 CPUFREQ_POLICY_NOTIFIER);
Konstantin Khlebnikov56836fb2012-12-15 00:22:02 +0100333 for_each_online_cpu(cpu)
334 cpufreq_stats_free_table(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 return ret;
336 }
337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 return 0;
339}
Dave Jones0a829c52009-01-18 01:49:04 -0500340static void __exit cpufreq_stats_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
342 unsigned int cpu;
Ashok Rajc32b6b82005-10-30 14:59:54 -0800343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 cpufreq_unregister_notifier(&notifier_policy_block,
345 CPUFREQ_POLICY_NOTIFIER);
346 cpufreq_unregister_notifier(&notifier_trans_block,
347 CPUFREQ_TRANSITION_NOTIFIER);
Viresh Kumar2d135942014-01-07 07:10:12 +0530348 for_each_online_cpu(cpu)
Satyam Sharma55395ae2007-10-02 13:28:15 -0700349 cpufreq_stats_free_table(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351
Dave Jones0a829c52009-01-18 01:49:04 -0500352MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
Viresh Kumar00d0b292015-01-06 21:09:00 +0530353MODULE_DESCRIPTION("Export cpufreq stats via sysfs");
Dave Jones0a829c52009-01-18 01:49:04 -0500354MODULE_LICENSE("GPL");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356module_init(cpufreq_stats_init);
357module_exit(cpufreq_stats_exit);