X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fcpufreq%2Fcpufreq_stats.c;h=c0ff97d375d79c83cdd3e52dbf65dc900c94c7a3;hb=e2f092ff9bf2ab515c14d2208b5f08c7d389d5d2;hp=9694b6ed3268edfe333214dbc71712c5f28e0fc8;hpb=bb1a813d3c49e57814958d2d52b5bb299204032e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 9694b6e..c0ff97d 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -9,7 +9,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include @@ -26,8 +25,7 @@ static spinlock_t cpufreq_stats_lock; #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ static struct freq_attr _attr_##_name = {\ - .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \ - .mode = _mode, }, \ + .attr = {.name = __stringify(_name), .mode = _mode, }, \ .show = _show,\ }; @@ -45,7 +43,7 @@ struct cpufreq_stats { #endif }; -static struct cpufreq_stats *cpufreq_stats_table[NR_CPUS]; +static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table); struct cpufreq_stats_attribute { struct attribute attr; @@ -60,7 +58,7 @@ cpufreq_stats_update (unsigned int cpu) cur_time = get_jiffies_64(); spin_lock(&cpufreq_stats_lock); - stat = cpufreq_stats_table[cpu]; + stat = per_cpu(cpufreq_stats_table, cpu); if (stat->time_in_state) stat->time_in_state[stat->last_index] = cputime64_add(stat->time_in_state[stat->last_index], @@ -73,11 +71,11 @@ cpufreq_stats_update (unsigned int cpu) static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) { - struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); + if (!stat) return 0; return sprintf(buf, "%d\n", - cpufreq_stats_table[stat->cpu]->total_trans); + per_cpu(cpufreq_stats_table, stat->cpu)->total_trans); } static ssize_t @@ -85,8 +83,8 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf) { ssize_t len = 0; int i; - struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); + if (!stat) return 0; cpufreq_stats_update(stat->cpu); for (i = 0; i < stat->state_num; i++) { @@ -103,8 +101,8 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) ssize_t len = 0; int i, j; - struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); + if (!stat) return 0; cpufreq_stats_update(stat->cpu); len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); @@ -116,7 +114,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) stat->freq_table[i]); } if (len >= PAGE_SIZE) - return len; + return PAGE_SIZE; len += snprintf(buf + len, PAGE_SIZE - len, "\n"); @@ -133,8 +131,12 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", stat->trans_table[i*stat->max_state+j]); } + if (len >= PAGE_SIZE) + break; len += snprintf(buf + len, PAGE_SIZE - len, "\n"); } + if (len >= PAGE_SIZE) + return PAGE_SIZE; return len; } CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table); @@ -166,10 +168,9 @@ freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) return -1; } -static void -cpufreq_stats_free_table (unsigned int cpu) +static void cpufreq_stats_free_table(unsigned int cpu) { - struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; + struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); if (policy && policy->cpu == cpu) sysfs_remove_group(&policy->kobj, &stats_attr_group); @@ -177,7 +178,7 @@ cpufreq_stats_free_table (unsigned int cpu) kfree(stat->time_in_state); kfree(stat); } - cpufreq_stats_table[cpu] = NULL; + per_cpu(cpufreq_stats_table, cpu) = NULL; if (policy) cpufreq_cpu_put(policy); } @@ -191,7 +192,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, struct cpufreq_policy *data; unsigned int alloc_size; unsigned int cpu = policy->cpu; - if (cpufreq_stats_table[cpu]) + if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -206,7 +207,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, goto error_out; stat->cpu = cpu; - cpufreq_stats_table[cpu] = stat; + per_cpu(cpufreq_stats_table, cpu) = stat; for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; @@ -250,7 +251,7 @@ error_out: cpufreq_cpu_put(data); error_get_fail: kfree(stat); - cpufreq_stats_table[cpu] = NULL; + per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; } @@ -283,16 +284,20 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, if (val != CPUFREQ_POSTCHANGE) return 0; - stat = cpufreq_stats_table[freq->cpu]; + stat = per_cpu(cpufreq_stats_table, freq->cpu); if (!stat) return 0; - old_index = freq_table_get_index(stat, freq->old); + + old_index = stat->last_index; new_index = freq_table_get_index(stat, freq->new); cpufreq_stats_update(freq->cpu); if (old_index == new_index) return 0; + if (old_index == -1 || new_index == -1) + return 0; + spin_lock(&cpufreq_stats_lock); stat->last_index = new_index; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS @@ -303,23 +308,26 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, return 0; } -static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) { unsigned int cpu = (unsigned long)hcpu; switch (action) { case CPU_ONLINE: + case CPU_ONLINE_FROZEN: cpufreq_update_policy(cpu); break; case CPU_DEAD: + case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); break; } return NOTIFY_OK; } -static struct notifier_block cpufreq_stat_cpu_notifier = +static struct notifier_block cpufreq_stat_cpu_notifier __refdata = { .notifier_call = cpufreq_stat_cpu_callback, }; @@ -350,13 +358,10 @@ __init cpufreq_stats_init(void) return ret; } - register_cpu_notifier(&cpufreq_stat_cpu_notifier); - lock_cpu_hotplug(); + register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { - cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, - (void *)(long)cpu); + cpufreq_update_policy(cpu); } - unlock_cpu_hotplug(); return 0; } static void @@ -368,17 +373,15 @@ __exit cpufreq_stats_exit(void) CPUFREQ_POLICY_NOTIFIER); cpufreq_unregister_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); - unregister_cpu_notifier(&cpufreq_stat_cpu_notifier); - lock_cpu_hotplug(); + unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { - cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD, - (void *)(long)cpu); + cpufreq_stats_free_table(cpu); } - unlock_cpu_hotplug(); } MODULE_AUTHOR ("Zou Nan hai "); -MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem"); +MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats " + "through sysfs filesystem"); MODULE_LICENSE ("GPL"); module_init(cpufreq_stats_init);