static int cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_freqs *freq = data; struct cpufreq_stats *stat; int old_index, new_index; if (val != CPUFREQ_POSTCHANGE) return 0; stat = cpufreq_stats_table[freq->cpu]; if (!stat) return 0; old_index = freq_table_get_index(stat, freq->old); 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 stat->trans_table[old_index * stat->max_state + new_index]++; #endif stat->total_trans++; spin_unlock(&cpufreq_stats_lock); return 0; }
static int cpufreq_stats_create_table(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table) { unsigned int i, j, count = 0, ret = 0; struct cpufreq_stats *stat; struct cpufreq_policy *data; unsigned int alloc_size; unsigned int cpu = policy->cpu; if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); if ((stat) == NULL) return -ENOMEM; data = cpufreq_cpu_get(cpu); if (data == NULL) { ret = -EINVAL; goto error_get_fail; } ret = sysfs_create_group(&data->kobj, &stats_attr_group); if (ret) goto error_out; stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; count++; } alloc_size = count * sizeof(int) + count * sizeof(u64); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS alloc_size += count * count * sizeof(int); #endif stat->max_state = count; stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stat->time_in_state) { ret = -ENOMEM; goto error_out; } stat->freq_table = (unsigned int *)(stat->time_in_state + count); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS stat->trans_table = stat->freq_table + count; #endif j = 0; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; if (freq_table_get_index(stat, freq) == -1) stat->freq_table[j++] = freq; } stat->state_num = j; spin_lock(&cpufreq_stats_lock); stat->last_time = get_jiffies_64(); stat->last_index = freq_table_get_index(stat, policy->cur); spin_unlock(&cpufreq_stats_lock); cpufreq_cpu_put(data); return 0; error_out: cpufreq_cpu_put(data); error_get_fail: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; }
static int cpufreq_stats_create_table(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table) { unsigned int i, j, count = 0, ret = 0; struct cpufreq_stats *stat; struct cpufreq_policy *data; unsigned int alloc_size; unsigned int cpu = policy->cpu; struct cpufreq_stats *prev_stat = per_cpu(prev_cpufreq_stats_table, cpu); if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); if ((stat) == NULL) return -ENOMEM; if (prev_stat) memcpy(stat, prev_stat, sizeof(*prev_stat)); data = cpufreq_cpu_get(cpu); if (data == NULL) { ret = -EINVAL; goto error_get_fail; } ret = sysfs_create_group(&data->kobj, &stats_attr_group); if (ret) goto error_out; stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; count++; } alloc_size = count * sizeof(int) + count * sizeof(u64); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS alloc_size += count * count * sizeof(int); #endif stat->max_state = count; stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stat->time_in_state) { ret = -ENOMEM; goto error_out; } stat->freq_table = (unsigned int *)(stat->time_in_state + count); #ifdef CONFIG_EXYNOS_MARCH_DYNAMIC_CPU_HOTPLUG if (cpu == 0 && cl0_time_in_state.init_complete ==0) { cl0_time_in_state.time_in_state = kzalloc(alloc_size, GFP_KERNEL); cl0_time_in_state.freq_table = (unsigned int *)(cl0_time_in_state.time_in_state + count); } else if (cpu == 4 && cl1_time_in_state.init_complete == 0) { cl1_time_in_state.time_in_state = kzalloc(alloc_size, GFP_KERNEL); cl1_time_in_state.freq_table = (unsigned int *)(cl1_time_in_state.time_in_state + count); } #endif #ifdef CONFIG_CPU_FREQ_STAT_DETAILS stat->trans_table = stat->freq_table + count; #endif j = 0; for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; if (freq_table_get_index(stat, freq) == -1) { #ifdef CONFIG_EXYNOS_MARCH_DYNAMIC_CPU_HOTPLUG if(cpu == 0 && cl0_time_in_state.init_complete == 0) { cl0_time_in_state.freq_table[j] = freq; } else if (cpu == 4 && cl1_time_in_state.init_complete == 0) { cl1_time_in_state.freq_table[j] = freq; } #endif stat->freq_table[j++] = freq; } } stat->state_num = j; #ifdef CONFIG_EXYNOS_MARCH_DYNAMIC_CPU_HOTPLUG if (cpu == 0 && cl0_time_in_state.init_complete == 0) { cl0_time_in_state.state_num = stat->state_num; cl0_time_in_state.init_complete = 1; } else if (cpu == 4 && cl1_time_in_state.init_complete == 0) { cl1_time_in_state.state_num = stat->state_num; cl1_time_in_state.init_complete = 1; } #endif if (prev_stat) { memcpy(stat->time_in_state, prev_stat->time_in_state, alloc_size); kfree(prev_stat->time_in_state); kfree(prev_stat); per_cpu(prev_cpufreq_stats_table, cpu) = NULL; } spin_lock(&cpufreq_stats_lock); stat->last_time = get_jiffies_64(); stat->last_index = freq_table_get_index(stat, policy->cur); if ((int)stat->last_index < 0) stat->last_index = 0; spin_unlock(&cpufreq_stats_lock); cpufreq_cpu_put(data); return 0; error_out: cpufreq_cpu_put(data); error_get_fail: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; }