示例#1
0
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;
}
示例#2
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;
}
示例#3
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;
	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;
}