11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/cpufreq/cpufreq_stats.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. 51da177e4SLinus Torvalds * (C) 2004 Zou Nan hai <nanhai.zou@intel.com>. 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds * published by the Free Software Foundation. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/config.h> 131da177e4SLinus Torvalds #include <linux/kernel.h> 141da177e4SLinus Torvalds #include <linux/sysdev.h> 151da177e4SLinus Torvalds #include <linux/cpu.h> 161da177e4SLinus Torvalds #include <linux/sysfs.h> 171da177e4SLinus Torvalds #include <linux/cpufreq.h> 181da177e4SLinus Torvalds #include <linux/jiffies.h> 191da177e4SLinus Torvalds #include <linux/percpu.h> 201da177e4SLinus Torvalds #include <linux/kobject.h> 211da177e4SLinus Torvalds #include <linux/spinlock.h> 22c32b6b8eSAshok Raj #include <linux/notifier.h> 2358f1df25SVenkatesh Pallipadi #include <asm/cputime.h> 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds static spinlock_t cpufreq_stats_lock; 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ 281da177e4SLinus Torvalds static struct freq_attr _attr_##_name = {\ 291da177e4SLinus Torvalds .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \ 301da177e4SLinus Torvalds .mode = _mode, }, \ 311da177e4SLinus Torvalds .show = _show,\ 321da177e4SLinus Torvalds }; 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds struct cpufreq_stats { 351da177e4SLinus Torvalds unsigned int cpu; 361da177e4SLinus Torvalds unsigned int total_trans; 371da177e4SLinus Torvalds unsigned long long last_time; 381da177e4SLinus Torvalds unsigned int max_state; 391da177e4SLinus Torvalds unsigned int state_num; 401da177e4SLinus Torvalds unsigned int last_index; 4158f1df25SVenkatesh Pallipadi cputime64_t *time_in_state; 421da177e4SLinus Torvalds unsigned int *freq_table; 431da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 441da177e4SLinus Torvalds unsigned int *trans_table; 451da177e4SLinus Torvalds #endif 461da177e4SLinus Torvalds }; 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static struct cpufreq_stats *cpufreq_stats_table[NR_CPUS]; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds struct cpufreq_stats_attribute { 511da177e4SLinus Torvalds struct attribute attr; 521da177e4SLinus Torvalds ssize_t(*show) (struct cpufreq_stats *, char *); 531da177e4SLinus Torvalds }; 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds static int 561da177e4SLinus Torvalds cpufreq_stats_update (unsigned int cpu) 571da177e4SLinus Torvalds { 581da177e4SLinus Torvalds struct cpufreq_stats *stat; 5958f1df25SVenkatesh Pallipadi unsigned long long cur_time; 6058f1df25SVenkatesh Pallipadi 6158f1df25SVenkatesh Pallipadi cur_time = get_jiffies_64(); 621da177e4SLinus Torvalds spin_lock(&cpufreq_stats_lock); 631da177e4SLinus Torvalds stat = cpufreq_stats_table[cpu]; 641da177e4SLinus Torvalds if (stat->time_in_state) 6558f1df25SVenkatesh Pallipadi stat->time_in_state[stat->last_index] = 6658f1df25SVenkatesh Pallipadi cputime64_add(stat->time_in_state[stat->last_index], 6758f1df25SVenkatesh Pallipadi cputime_sub(cur_time, stat->last_time)); 6858f1df25SVenkatesh Pallipadi stat->last_time = cur_time; 691da177e4SLinus Torvalds spin_unlock(&cpufreq_stats_lock); 701da177e4SLinus Torvalds return 0; 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds static ssize_t 741da177e4SLinus Torvalds show_total_trans(struct cpufreq_policy *policy, char *buf) 751da177e4SLinus Torvalds { 761da177e4SLinus Torvalds struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; 771da177e4SLinus Torvalds if (!stat) 781da177e4SLinus Torvalds return 0; 791da177e4SLinus Torvalds return sprintf(buf, "%d\n", 801da177e4SLinus Torvalds cpufreq_stats_table[stat->cpu]->total_trans); 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds static ssize_t 841da177e4SLinus Torvalds show_time_in_state(struct cpufreq_policy *policy, char *buf) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds ssize_t len = 0; 871da177e4SLinus Torvalds int i; 881da177e4SLinus Torvalds struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; 891da177e4SLinus Torvalds if (!stat) 901da177e4SLinus Torvalds return 0; 911da177e4SLinus Torvalds cpufreq_stats_update(stat->cpu); 921da177e4SLinus Torvalds for (i = 0; i < stat->state_num; i++) { 9358f1df25SVenkatesh Pallipadi len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], 9458f1df25SVenkatesh Pallipadi (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i])); 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds return len; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 1001da177e4SLinus Torvalds static ssize_t 1011da177e4SLinus Torvalds show_trans_table(struct cpufreq_policy *policy, char *buf) 1021da177e4SLinus Torvalds { 1031da177e4SLinus Torvalds ssize_t len = 0; 1041da177e4SLinus Torvalds int i, j; 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; 1071da177e4SLinus Torvalds if (!stat) 1081da177e4SLinus Torvalds return 0; 1091da177e4SLinus Torvalds cpufreq_stats_update(stat->cpu); 11058f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); 11158f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, " : "); 1121da177e4SLinus Torvalds for (i = 0; i < stat->state_num; i++) { 1131da177e4SLinus Torvalds if (len >= PAGE_SIZE) 1141da177e4SLinus Torvalds break; 11558f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", 11658f1df25SVenkatesh Pallipadi stat->freq_table[i]); 11758f1df25SVenkatesh Pallipadi } 11858f1df25SVenkatesh Pallipadi if (len >= PAGE_SIZE) 11958f1df25SVenkatesh Pallipadi return len; 12058f1df25SVenkatesh Pallipadi 12158f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, "\n"); 12258f1df25SVenkatesh Pallipadi 12358f1df25SVenkatesh Pallipadi for (i = 0; i < stat->state_num; i++) { 12458f1df25SVenkatesh Pallipadi if (len >= PAGE_SIZE) 12558f1df25SVenkatesh Pallipadi break; 12658f1df25SVenkatesh Pallipadi 12758f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ", 1281da177e4SLinus Torvalds stat->freq_table[i]); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds for (j = 0; j < stat->state_num; j++) { 1311da177e4SLinus Torvalds if (len >= PAGE_SIZE) 1321da177e4SLinus Torvalds break; 13358f1df25SVenkatesh Pallipadi len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", 1341da177e4SLinus Torvalds stat->trans_table[i*stat->max_state+j]); 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds len += snprintf(buf + len, PAGE_SIZE - len, "\n"); 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds return len; 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table); 1411da177e4SLinus Torvalds #endif 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds CPUFREQ_STATDEVICE_ATTR(total_trans,0444,show_total_trans); 1441da177e4SLinus Torvalds CPUFREQ_STATDEVICE_ATTR(time_in_state,0444,show_time_in_state); 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds static struct attribute *default_attrs[] = { 1471da177e4SLinus Torvalds &_attr_total_trans.attr, 1481da177e4SLinus Torvalds &_attr_time_in_state.attr, 1491da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 1501da177e4SLinus Torvalds &_attr_trans_table.attr, 1511da177e4SLinus Torvalds #endif 1521da177e4SLinus Torvalds NULL 1531da177e4SLinus Torvalds }; 1541da177e4SLinus Torvalds static struct attribute_group stats_attr_group = { 1551da177e4SLinus Torvalds .attrs = default_attrs, 1561da177e4SLinus Torvalds .name = "stats" 1571da177e4SLinus Torvalds }; 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds static int 1601da177e4SLinus Torvalds freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) 1611da177e4SLinus Torvalds { 1621da177e4SLinus Torvalds int index; 1631da177e4SLinus Torvalds for (index = 0; index < stat->max_state; index++) 1641da177e4SLinus Torvalds if (stat->freq_table[index] == freq) 1651da177e4SLinus Torvalds return index; 1661da177e4SLinus Torvalds return -1; 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds static void 1701da177e4SLinus Torvalds cpufreq_stats_free_table (unsigned int cpu) 1711da177e4SLinus Torvalds { 1721da177e4SLinus Torvalds struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; 1731da177e4SLinus Torvalds struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 1741da177e4SLinus Torvalds if (policy && policy->cpu == cpu) 1751da177e4SLinus Torvalds sysfs_remove_group(&policy->kobj, &stats_attr_group); 1761da177e4SLinus Torvalds if (stat) { 1771da177e4SLinus Torvalds kfree(stat->time_in_state); 1781da177e4SLinus Torvalds kfree(stat); 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds cpufreq_stats_table[cpu] = NULL; 1811da177e4SLinus Torvalds if (policy) 1821da177e4SLinus Torvalds cpufreq_cpu_put(policy); 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds static int 1861da177e4SLinus Torvalds cpufreq_stats_create_table (struct cpufreq_policy *policy, 1871da177e4SLinus Torvalds struct cpufreq_frequency_table *table) 1881da177e4SLinus Torvalds { 1891da177e4SLinus Torvalds unsigned int i, j, count = 0, ret = 0; 1901da177e4SLinus Torvalds struct cpufreq_stats *stat; 1911da177e4SLinus Torvalds struct cpufreq_policy *data; 1921da177e4SLinus Torvalds unsigned int alloc_size; 1931da177e4SLinus Torvalds unsigned int cpu = policy->cpu; 1941da177e4SLinus Torvalds if (cpufreq_stats_table[cpu]) 1951da177e4SLinus Torvalds return -EBUSY; 196e98df50cSDave Jones if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) 1971da177e4SLinus Torvalds return -ENOMEM; 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds data = cpufreq_cpu_get(cpu); 200bc7b26fdSDave Jones if (data == NULL) { 201bc7b26fdSDave Jones ret = -EINVAL; 202bc7b26fdSDave Jones goto error_get_fail; 203bc7b26fdSDave Jones } 204bc7b26fdSDave Jones 2051da177e4SLinus Torvalds if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) 2061da177e4SLinus Torvalds goto error_out; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds stat->cpu = cpu; 2091da177e4SLinus Torvalds cpufreq_stats_table[cpu] = stat; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) { 2121da177e4SLinus Torvalds unsigned int freq = table[i].frequency; 2131da177e4SLinus Torvalds if (freq == CPUFREQ_ENTRY_INVALID) 2141da177e4SLinus Torvalds continue; 2151da177e4SLinus Torvalds count++; 2161da177e4SLinus Torvalds } 2171da177e4SLinus Torvalds 21858f1df25SVenkatesh Pallipadi alloc_size = count * sizeof(int) + count * sizeof(cputime64_t); 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 2211da177e4SLinus Torvalds alloc_size += count * count * sizeof(int); 2221da177e4SLinus Torvalds #endif 2231da177e4SLinus Torvalds stat->max_state = count; 224e98df50cSDave Jones stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); 2251da177e4SLinus Torvalds if (!stat->time_in_state) { 2261da177e4SLinus Torvalds ret = -ENOMEM; 2271da177e4SLinus Torvalds goto error_out; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds stat->freq_table = (unsigned int *)(stat->time_in_state + count); 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 2321da177e4SLinus Torvalds stat->trans_table = stat->freq_table + count; 2331da177e4SLinus Torvalds #endif 2341da177e4SLinus Torvalds j = 0; 2351da177e4SLinus Torvalds for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { 2361da177e4SLinus Torvalds unsigned int freq = table[i].frequency; 2371da177e4SLinus Torvalds if (freq == CPUFREQ_ENTRY_INVALID) 2381da177e4SLinus Torvalds continue; 2391da177e4SLinus Torvalds if (freq_table_get_index(stat, freq) == -1) 2401da177e4SLinus Torvalds stat->freq_table[j++] = freq; 2411da177e4SLinus Torvalds } 2421da177e4SLinus Torvalds stat->state_num = j; 2431da177e4SLinus Torvalds spin_lock(&cpufreq_stats_lock); 24458f1df25SVenkatesh Pallipadi stat->last_time = get_jiffies_64(); 2451da177e4SLinus Torvalds stat->last_index = freq_table_get_index(stat, policy->cur); 2461da177e4SLinus Torvalds spin_unlock(&cpufreq_stats_lock); 2471da177e4SLinus Torvalds cpufreq_cpu_put(data); 2481da177e4SLinus Torvalds return 0; 2491da177e4SLinus Torvalds error_out: 2501da177e4SLinus Torvalds cpufreq_cpu_put(data); 251b7fb358cSDave Jones error_get_fail: 2521da177e4SLinus Torvalds kfree(stat); 2531da177e4SLinus Torvalds cpufreq_stats_table[cpu] = NULL; 2541da177e4SLinus Torvalds return ret; 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds static int 2581da177e4SLinus Torvalds cpufreq_stat_notifier_policy (struct notifier_block *nb, unsigned long val, 2591da177e4SLinus Torvalds void *data) 2601da177e4SLinus Torvalds { 2611da177e4SLinus Torvalds int ret; 2621da177e4SLinus Torvalds struct cpufreq_policy *policy = data; 2631da177e4SLinus Torvalds struct cpufreq_frequency_table *table; 2641da177e4SLinus Torvalds unsigned int cpu = policy->cpu; 2651da177e4SLinus Torvalds if (val != CPUFREQ_NOTIFY) 2661da177e4SLinus Torvalds return 0; 2671da177e4SLinus Torvalds table = cpufreq_frequency_get_table(cpu); 2681da177e4SLinus Torvalds if (!table) 2691da177e4SLinus Torvalds return 0; 2701da177e4SLinus Torvalds if ((ret = cpufreq_stats_create_table(policy, table))) 2711da177e4SLinus Torvalds return ret; 2721da177e4SLinus Torvalds return 0; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds static int 2761da177e4SLinus Torvalds cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, 2771da177e4SLinus Torvalds void *data) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct cpufreq_freqs *freq = data; 2801da177e4SLinus Torvalds struct cpufreq_stats *stat; 2811da177e4SLinus Torvalds int old_index, new_index; 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds if (val != CPUFREQ_POSTCHANGE) 2841da177e4SLinus Torvalds return 0; 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds stat = cpufreq_stats_table[freq->cpu]; 2871da177e4SLinus Torvalds if (!stat) 2881da177e4SLinus Torvalds return 0; 2891da177e4SLinus Torvalds old_index = freq_table_get_index(stat, freq->old); 2901da177e4SLinus Torvalds new_index = freq_table_get_index(stat, freq->new); 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds cpufreq_stats_update(freq->cpu); 2931da177e4SLinus Torvalds if (old_index == new_index) 2941da177e4SLinus Torvalds return 0; 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds spin_lock(&cpufreq_stats_lock); 2971da177e4SLinus Torvalds stat->last_index = new_index; 2981da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_STAT_DETAILS 2991da177e4SLinus Torvalds stat->trans_table[old_index * stat->max_state + new_index]++; 3001da177e4SLinus Torvalds #endif 3011da177e4SLinus Torvalds stat->total_trans++; 3021da177e4SLinus Torvalds spin_unlock(&cpufreq_stats_lock); 3031da177e4SLinus Torvalds return 0; 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds 306bb1a813dSSam Ravnborg static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, 307c32b6b8eSAshok Raj unsigned long action, void *hcpu) 308c32b6b8eSAshok Raj { 309c32b6b8eSAshok Raj unsigned int cpu = (unsigned long)hcpu; 310c32b6b8eSAshok Raj 311c32b6b8eSAshok Raj switch (action) { 312c32b6b8eSAshok Raj case CPU_ONLINE: 313c32b6b8eSAshok Raj cpufreq_update_policy(cpu); 314c32b6b8eSAshok Raj break; 315c32b6b8eSAshok Raj case CPU_DEAD: 316c32b6b8eSAshok Raj cpufreq_stats_free_table(cpu); 317c32b6b8eSAshok Raj break; 318c32b6b8eSAshok Raj } 319c32b6b8eSAshok Raj return NOTIFY_OK; 320c32b6b8eSAshok Raj } 321c32b6b8eSAshok Raj 322c32b6b8eSAshok Raj static struct notifier_block cpufreq_stat_cpu_notifier = 323c32b6b8eSAshok Raj { 324c32b6b8eSAshok Raj .notifier_call = cpufreq_stat_cpu_callback, 325c32b6b8eSAshok Raj }; 326c32b6b8eSAshok Raj 3271da177e4SLinus Torvalds static struct notifier_block notifier_policy_block = { 3281da177e4SLinus Torvalds .notifier_call = cpufreq_stat_notifier_policy 3291da177e4SLinus Torvalds }; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds static struct notifier_block notifier_trans_block = { 3321da177e4SLinus Torvalds .notifier_call = cpufreq_stat_notifier_trans 3331da177e4SLinus Torvalds }; 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds static int 3361da177e4SLinus Torvalds __init cpufreq_stats_init(void) 3371da177e4SLinus Torvalds { 3381da177e4SLinus Torvalds int ret; 3391da177e4SLinus Torvalds unsigned int cpu; 340c32b6b8eSAshok Raj 3411da177e4SLinus Torvalds spin_lock_init(&cpufreq_stats_lock); 3421da177e4SLinus Torvalds if ((ret = cpufreq_register_notifier(¬ifier_policy_block, 3431da177e4SLinus Torvalds CPUFREQ_POLICY_NOTIFIER))) 3441da177e4SLinus Torvalds return ret; 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds if ((ret = cpufreq_register_notifier(¬ifier_trans_block, 3471da177e4SLinus Torvalds CPUFREQ_TRANSITION_NOTIFIER))) { 3481da177e4SLinus Torvalds cpufreq_unregister_notifier(¬ifier_policy_block, 3491da177e4SLinus Torvalds CPUFREQ_POLICY_NOTIFIER); 3501da177e4SLinus Torvalds return ret; 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds 35365edc68cSChandra Seetharaman register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); 354c32b6b8eSAshok Raj lock_cpu_hotplug(); 355c32b6b8eSAshok Raj for_each_online_cpu(cpu) { 356c32b6b8eSAshok Raj cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, 357c32b6b8eSAshok Raj (void *)(long)cpu); 358c32b6b8eSAshok Raj } 359c32b6b8eSAshok Raj unlock_cpu_hotplug(); 3601da177e4SLinus Torvalds return 0; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds static void 3631da177e4SLinus Torvalds __exit cpufreq_stats_exit(void) 3641da177e4SLinus Torvalds { 3651da177e4SLinus Torvalds unsigned int cpu; 366c32b6b8eSAshok Raj 3671da177e4SLinus Torvalds cpufreq_unregister_notifier(¬ifier_policy_block, 3681da177e4SLinus Torvalds CPUFREQ_POLICY_NOTIFIER); 3691da177e4SLinus Torvalds cpufreq_unregister_notifier(¬ifier_trans_block, 3701da177e4SLinus Torvalds CPUFREQ_TRANSITION_NOTIFIER); 37165edc68cSChandra Seetharaman unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); 372c32b6b8eSAshok Raj lock_cpu_hotplug(); 373c32b6b8eSAshok Raj for_each_online_cpu(cpu) { 374c32b6b8eSAshok Raj cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD, 375c32b6b8eSAshok Raj (void *)(long)cpu); 376c32b6b8eSAshok Raj } 377c32b6b8eSAshok Raj unlock_cpu_hotplug(); 3781da177e4SLinus Torvalds } 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); 3811da177e4SLinus Torvalds MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem"); 3821da177e4SLinus Torvalds MODULE_LICENSE ("GPL"); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds module_init(cpufreq_stats_init); 3851da177e4SLinus Torvalds module_exit(cpufreq_stats_exit); 386