Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c22b737e authored by Ruchi Kandoi's avatar Ruchi Kandoi Committed by alexax66
Browse files

cpufreq_stats: Adds the fucntionality to load current values for each frequency for all the cores.



The current values for the cpu cores needs to be added to the device
tree for this functionaly to work. It loads the current values for each
frequecy in uA for all the cores.

Change-Id: If03311aaeb3e4c09375dd0beb9ad4fbb254b5c08
Signed-off-by: default avatarRuchi Kandoi <kandoiruchi@google.com>

Original commit: https://github.com/dianlujitao/CAF_kernel_msm-3.10/commit/8d12562a74922eac859dcec9c43d34d8fd1a9fd1
parent cc108002
Loading
Loading
Loading
Loading
+139 −29
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/notifier.h>
#include <linux/notifier.h>
#include <linux/sort.h>
#include <linux/sort.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/of.h>
#include <asm/cputime.h>
#include <asm/cputime.h>
#ifdef CONFIG_BL_SWITCHER
#ifdef CONFIG_BL_SWITCHER
#include <asm/bL_switcher.h>
#include <asm/bL_switcher.h>
@@ -43,6 +44,12 @@ struct cpufreq_stats {
#endif
#endif
};
};


struct cpufreq_power_stats {
	unsigned int state_num;
	unsigned int *curr;
	unsigned int *freq_table;
};

struct all_cpufreq_stats {
struct all_cpufreq_stats {
	unsigned int state_num;
	unsigned int state_num;
	cputime64_t *time_in_state;
	cputime64_t *time_in_state;
@@ -59,6 +66,7 @@ static struct all_freq_table *all_freq_table;
static DEFINE_PER_CPU(struct all_cpufreq_stats *, all_cpufreq_stats);
static DEFINE_PER_CPU(struct all_cpufreq_stats *, all_cpufreq_stats);
static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table);
static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table);
static DEFINE_PER_CPU(struct cpufreq_stats *, prev_cpufreq_stats_table);
static DEFINE_PER_CPU(struct cpufreq_stats *, prev_cpufreq_stats_table);
static DEFINE_PER_CPU(struct cpufreq_power_stats *, cpufreq_power_stats);


struct cpufreq_stats_attribute {
struct cpufreq_stats_attribute {
	struct attribute attr;
	struct attribute attr;
@@ -129,6 +137,29 @@ static int get_index_all_cpufreq_stat(struct all_cpufreq_stats *all_stat,
	return -1;
	return -1;
}
}


static ssize_t show_current_in_state(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	ssize_t len = 0;
	unsigned int i, cpu;
	struct cpufreq_power_stats *powerstats;

	spin_lock(&cpufreq_stats_lock);
	for_each_possible_cpu(cpu) {
		powerstats = per_cpu(cpufreq_power_stats, cpu);
		if (!powerstats)
			continue;
		len += scnprintf(buf + len, PAGE_SIZE - len, "CPU%d:", cpu);
		for (i = 0; i < powerstats->state_num; i++)
			len += scnprintf(buf + len, PAGE_SIZE - len,
					"%d=%d ", powerstats->freq_table[i],
					powerstats->curr[i]);
		len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
	}
	spin_unlock(&cpufreq_stats_lock);
	return len;
}

static ssize_t show_all_time_in_state(struct kobject *kobj,
static ssize_t show_all_time_in_state(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
		struct kobj_attribute *attr, char *buf)
{
{
@@ -238,6 +269,9 @@ static struct attribute_group stats_attr_group = {
static struct kobj_attribute _attr_all_time_in_state = __ATTR(all_time_in_state,
static struct kobj_attribute _attr_all_time_in_state = __ATTR(all_time_in_state,
		0444, show_all_time_in_state, NULL);
		0444, show_all_time_in_state, NULL);


static struct kobj_attribute _attr_current_in_state = __ATTR(current_in_state,
		0444, show_current_in_state, NULL);

static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
{
{
	int index;
	int index;
@@ -330,10 +364,27 @@ static void cpufreq_allstats_free(void)
	}
	}
}
}


static void cpufreq_powerstats_free(void)
{
	int cpu;
	struct cpufreq_power_stats *powerstats;

	sysfs_remove_file(cpufreq_global_kobject, &_attr_current_in_state.attr);

	for_each_possible_cpu(cpu) {
		powerstats = per_cpu(cpufreq_power_stats, cpu);
		if (!powerstats)
			continue;
		kfree(powerstats->curr);
		kfree(powerstats);
		per_cpu(cpufreq_power_stats, cpu) = NULL;
	}
}

static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
		struct cpufreq_frequency_table *table)
		struct cpufreq_frequency_table *table, int count)
{
{
	unsigned int i, j, count = 0, ret = 0;
	unsigned int i, j, ret = 0;
	struct cpufreq_stats *stat;
	struct cpufreq_stats *stat;
	struct cpufreq_policy *data;
	struct cpufreq_policy *data;
	unsigned int alloc_size;
	unsigned int alloc_size;
@@ -362,13 +413,6 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
	stat->cpu = cpu;
	stat->cpu = cpu;
	per_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;
		if (freq == CPUFREQ_ENTRY_INVALID)
			continue;
		count++;
	}

	alloc_size = count * sizeof(int) + count * sizeof(u64);
	alloc_size = count * sizeof(int) + count * sizeof(u64);


#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
@@ -437,6 +481,54 @@ static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
	stat->cpu = policy->cpu;
	stat->cpu = policy->cpu;
}
}


static void cpufreq_powerstats_create(unsigned int cpu,
		struct cpufreq_frequency_table *table, int count) {
	unsigned int alloc_size, i = 0, j = 0, ret = 0;
	struct cpufreq_power_stats *powerstats;
	struct device_node *cpu_node;
	char device_path[16];

	powerstats = kzalloc(sizeof(struct cpufreq_power_stats),
			GFP_KERNEL);
	if (!powerstats)
		return;

	/* Allocate memory for freq table per cpu as well as clockticks per
	 * freq*/
	alloc_size = count * sizeof(unsigned int) +
		count * sizeof(unsigned int);
	powerstats->curr = kzalloc(alloc_size, GFP_KERNEL);
	if (!powerstats->curr) {
		kfree(powerstats);
		return;
	}
	powerstats->freq_table = powerstats->curr + count;

	spin_lock(&cpufreq_stats_lock);
	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END && j < count; i++) {
		unsigned int freq = table[i].frequency;

		if (freq == CPUFREQ_ENTRY_INVALID)
			continue;
		powerstats->freq_table[j++] = freq;
	}
	powerstats->state_num = j;

	snprintf(device_path, sizeof(device_path), "/cpus/cpu@%d", cpu);
	cpu_node = of_find_node_by_path(device_path);
	if (cpu_node) {
		ret = of_property_read_u32_array(cpu_node, "current",
				powerstats->curr, count);
		if (ret) {
			kfree(powerstats->curr);
			kfree(powerstats);
			powerstats = NULL;
		}
	}
	per_cpu(cpufreq_power_stats, cpu) = powerstats;
	spin_unlock(&cpufreq_stats_lock);
}

static int compare_for_sort(const void *lhs_ptr, const void *rhs_ptr)
static int compare_for_sort(const void *lhs_ptr, const void *rhs_ptr)
{
{
	unsigned int lhs = *(const unsigned int *)(lhs_ptr);
	unsigned int lhs = *(const unsigned int *)(lhs_ptr);
@@ -481,24 +573,14 @@ static void add_all_freq_table(unsigned int freq)
	all_freq_table->freq_table[all_freq_table->table_size++] = freq;
	all_freq_table->freq_table[all_freq_table->table_size++] = freq;
}
}


static void cpufreq_allstats_create(unsigned int cpu)
static void cpufreq_allstats_create(unsigned int cpu,
		struct cpufreq_frequency_table *table, int count)
{
{
	int i , j = 0;
	int i , j = 0;
	unsigned int alloc_size, count = 0;
	unsigned int alloc_size;
	struct cpufreq_frequency_table *table = cpufreq_frequency_get_table(cpu);
	struct all_cpufreq_stats *all_stat;
	struct all_cpufreq_stats *all_stat;
	bool sort_needed = false;
	bool sort_needed = false;


	if (!table)
		return;

	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
		unsigned int freq = table[i].frequency;
		if (freq == CPUFREQ_ENTRY_INVALID)
			continue;
		count++;
	}

	all_stat = kzalloc(sizeof(struct all_cpufreq_stats),
	all_stat = kzalloc(sizeof(struct all_cpufreq_stats),
			GFP_KERNEL);
			GFP_KERNEL);
	if (!all_stat) {
	if (!all_stat) {
@@ -540,7 +622,7 @@ static void cpufreq_allstats_create(unsigned int cpu)
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
		unsigned long val, void *data)
		unsigned long val, void *data)
{
{
	int ret;
	int ret, count = 0, i;
	struct cpufreq_policy *policy = data;
	struct cpufreq_policy *policy = data;
	struct cpufreq_frequency_table *table;
	struct cpufreq_frequency_table *table;
	unsigned int cpu = policy->cpu;
	unsigned int cpu = policy->cpu;
@@ -556,10 +638,21 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
	if (!table)
	if (!table)
		return 0;
		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))
	if (!per_cpu(all_cpufreq_stats, cpu))
		cpufreq_allstats_create(cpu);
		cpufreq_allstats_create(cpu, table, count);


	ret = cpufreq_stats_create_table(policy, table);
	if (!per_cpu(cpufreq_power_stats, cpu))
		cpufreq_powerstats_create(cpu, table, count);

	ret = cpufreq_stats_create_table(policy, table, count);
	if (ret)
	if (ret)
		return ret;
		return ret;
	return 0;
	return 0;
@@ -605,7 +698,7 @@ static int cpufreq_stats_create_table_cpu(unsigned int cpu)
{
{
	struct cpufreq_policy *policy;
	struct cpufreq_policy *policy;
	struct cpufreq_frequency_table *table;
	struct cpufreq_frequency_table *table;
	int ret = -ENODEV;
	int ret = -ENODEV, i, count = 0;


	policy = cpufreq_cpu_get(cpu);
	policy = cpufreq_cpu_get(cpu);
	if (!policy)
	if (!policy)
@@ -615,10 +708,21 @@ static int cpufreq_stats_create_table_cpu(unsigned int cpu)
	if (!table)
	if (!table)
		goto out;
		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))
	if (!per_cpu(all_cpufreq_stats, cpu))
		cpufreq_allstats_create(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);
	ret = cpufreq_stats_create_table(policy, table, count);


out:
out:
	cpufreq_cpu_put(policy);
	cpufreq_cpu_put(policy);
@@ -696,7 +800,12 @@ static int cpufreq_stats_setup(void)
	ret = sysfs_create_file(cpufreq_global_kobject,
	ret = sysfs_create_file(cpufreq_global_kobject,
			&_attr_all_time_in_state.attr);
			&_attr_all_time_in_state.attr);
	if (ret)
	if (ret)
		pr_warn("Error creating sysfs file for cpufreq stats\n");
		pr_warn("Cannot create sysfs file for cpufreq stats\n");

	ret = sysfs_create_file(cpufreq_global_kobject,
			&_attr_current_in_state.attr);
	if (ret)
		pr_warn("Cannot create sysfs file for cpufreq current stats\n");


	return 0;
	return 0;
}
}
@@ -763,6 +872,7 @@ static void __exit cpufreq_stats_exit(void)
	bL_switcher_unregister_notifier(&switcher_notifier);
	bL_switcher_unregister_notifier(&switcher_notifier);
#endif
#endif
	cpufreq_stats_cleanup();
	cpufreq_stats_cleanup();
	cpufreq_powerstats_free();
}
}


MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");