static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { int ret; struct cpufreq_policy *policy = data; struct cpufreq_frequency_table *table; unsigned int cpu = policy->cpu; if (val == CPUFREQ_UPDATE_POLICY_CPU) { cpufreq_stats_update_policy_cpu(policy); return 0; } if (val != CPUFREQ_NOTIFY) return 0; table = cpufreq_frequency_get_table(cpu); if (!table) return 0; if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu); ret = cpufreq_stats_create_table(policy, table); if (ret) return ret; return 0; }
static void cpufreq_stats_create_table(unsigned int cpu) { struct cpufreq_policy *policy; struct cpufreq_frequency_table *table; int i, cpu_num, count = 0; /* * "likely(!policy)" because normally cpufreq_stats will be registered * before cpufreq driver */ policy = cpufreq_cpu_get(cpu); if (likely(!policy)) return; table = cpufreq_frequency_get_table(policy->cpu); if (likely(table)) { for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq != CPUFREQ_ENTRY_INVALID) count++; } if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu, table, count); for_each_possible_cpu(cpu_num) { if (!per_cpu(cpufreq_power_stats, cpu)) cpufreq_powerstats_create(cpu, table, count); } __cpufreq_stats_create_table(policy, table, count); } cpufreq_cpu_put(policy); }
static int cpufreq_stats_create_table_cpu(unsigned int cpu) { struct cpufreq_policy *policy; struct cpufreq_frequency_table *table; int ret = -ENODEV, i, count = 0; policy = cpufreq_cpu_get(cpu); if (!policy) return -ENODEV; table = cpufreq_frequency_get_table(cpu); if (!table) goto out; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; count++; } if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu, table, count); if (!per_cpu(cpufreq_power_stats, cpu)) cpufreq_powerstats_create(cpu, table, count); ret = cpufreq_stats_create_table(policy, table, count); out: cpufreq_cpu_put(policy); return ret; }
static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { int ret, count = 0, i; struct cpufreq_policy *policy = data; struct cpufreq_frequency_table *table; unsigned int cpu = policy->cpu; if (val != CPUFREQ_NOTIFY) return 0; table = cpufreq_frequency_get_table(cpu); if (!table) return 0; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; count++; } if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu, table, count); if (!per_cpu(cpufreq_power_stats, cpu)) cpufreq_powerstats_create(cpu, table, count); ret = cpufreq_stats_create_table(policy, table, count); if (ret) return ret; return 0; }
static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { int ret, count = 0, i; struct cpufreq_policy *policy = data; struct cpufreq_frequency_table *table; unsigned int cpu_num, cpu = policy->cpu; if (val == CPUFREQ_UPDATE_POLICY_CPU) { cpufreq_stats_update_policy_cpu(policy); return 0; } table = cpufreq_frequency_get_table(cpu); if (!table) return 0; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; count++; } if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu, table, count); for_each_possible_cpu(cpu_num) { if (!per_cpu(cpufreq_power_stats, cpu_num)) cpufreq_powerstats_create(cpu_num, table, count); } if (val == CPUFREQ_CREATE_POLICY) ret = __cpufreq_stats_create_table(policy, table, count); else if (val == CPUFREQ_REMOVE_POLICY) __cpufreq_stats_free_table(policy); return ret; }
static int __init cpufreq_stats_init(void) { int ret; unsigned int cpu; spin_lock_init(&cpufreq_stats_lock); ret = cpufreq_register_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); if (ret) return ret; register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) cpufreq_update_policy(cpu); ret = cpufreq_register_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); if (ret) { cpufreq_unregister_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) cpufreq_stats_free_table(cpu); return ret; } create_all_freq_table(); for_each_possible_cpu(cpu) { cpufreq_allstats_create(cpu); } if (all_freq_table && all_freq_table->freq_table) sort(all_freq_table->freq_table, all_freq_table->table_size, sizeof(unsigned int), &compare_for_sort, NULL); ret = sysfs_create_file(cpufreq_global_kobject, &_attr_all_time_in_state.attr); if (ret) pr_warn("Error creating sysfs file for cpufreq stats\n"); return 0; }
static int cpufreq_stats_create_table_cpu(unsigned int cpu) { struct cpufreq_policy *policy; struct cpufreq_frequency_table *table; int ret = -ENODEV; policy = cpufreq_cpu_get(cpu); if (!policy) return -ENODEV; table = cpufreq_frequency_get_table(cpu); if (!table) goto out; if (!per_cpu(all_cpufreq_stats, cpu)) cpufreq_allstats_create(cpu); ret = cpufreq_stats_create_table(policy, table); out: cpufreq_cpu_put(policy); return ret; }