summaryrefslogtreecommitdiff
path: root/target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch')
-rw-r--r--target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch304
1 files changed, 304 insertions, 0 deletions
diff --git a/target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch b/target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch
new file mode 100644
index 0000000..f526eab
--- /dev/null
+++ b/target/linux/xburst/patches-3.8/0010-cpufreq_stats-Support-runtime-changes-to-frequency-t.patch
@@ -0,0 +1,304 @@
+From ca40c7542f0cd0e0dfa074bd4ccefc04b8561427 Mon Sep 17 00:00:00 2001
+From: Maarten ter Huurne <maarten@treewalker.org>
+Date: Tue, 2 Aug 2011 10:26:09 +0200
+Subject: [PATCH 10/21] cpufreq_stats: Support runtime changes to frequency
+ table.
+
+---
+ drivers/cpufreq/cpufreq_stats.c | 161 ++++++++++++++++++++-------------------
+ 1 files changed, 83 insertions(+), 78 deletions(-)
+
+--- a/drivers/cpufreq/cpufreq_stats.c
++++ b/drivers/cpufreq/cpufreq_stats.c
+@@ -20,6 +20,7 @@
+ #include <linux/kobject.h>
+ #include <linux/spinlock.h>
+ #include <linux/notifier.h>
++#include <linux/string.h>
+ #include <asm/cputime.h>
+
+ static spinlock_t cpufreq_stats_lock;
+@@ -36,7 +37,7 @@ struct cpufreq_stats {
+ unsigned long long last_time;
+ unsigned int max_state;
+ unsigned int state_num;
+- unsigned int last_index;
++ int last_index;
+ u64 *time_in_state;
+ unsigned int *freq_table;
+ #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+@@ -59,7 +60,7 @@ static int cpufreq_stats_update(unsigned
+ cur_time = get_jiffies_64();
+ spin_lock(&cpufreq_stats_lock);
+ stat = per_cpu(cpufreq_stats_table, cpu);
+- if (stat->time_in_state)
++ if (stat->time_in_state && stat->last_index != -1)
+ stat->time_in_state[stat->last_index] +=
+ cur_time - stat->last_time;
+ stat->last_time = cur_time;
+@@ -81,7 +82,7 @@ static ssize_t show_time_in_state(struct
+ ssize_t len = 0;
+ int i;
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
+- if (!stat)
++ if (!stat || !stat->time_in_state)
+ return 0;
+ cpufreq_stats_update(stat->cpu);
+ for (i = 0; i < stat->state_num; i++) {
+@@ -99,7 +100,7 @@ static ssize_t show_trans_table(struct c
+ int i, j;
+
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
+- if (!stat)
++ if (!stat || !stat->trans_table)
+ return 0;
+ cpufreq_stats_update(stat->cpu);
+ len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
+@@ -158,63 +159,35 @@ static struct attribute_group stats_attr
+ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
+ {
+ int index;
+- for (index = 0; index < stat->max_state; index++)
+- if (stat->freq_table[index] == freq)
+- return index;
++ if (stat->freq_table)
++ for (index = 0; index < stat->max_state; index++)
++ if (stat->freq_table[index] == freq)
++ return index;
+ return -1;
+ }
+
+-/* should be called late in the CPU removal sequence so that the stats
+- * memory is still available in case someone tries to use it.
+- */
+ static void cpufreq_stats_free_table(unsigned int 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);
+ if (stat) {
+ kfree(stat->time_in_state);
+ kfree(stat);
+ }
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
+-}
+-
+-/* must be called early in the CPU removal sequence (before
+- * cpufreq_remove_dev) so that policy is still valid.
+- */
+-static void cpufreq_stats_free_sysfs(unsigned int cpu)
+-{
+- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+- if (policy && policy->cpu == cpu)
+- sysfs_remove_group(&policy->kobj, &stats_attr_group);
+ if (policy)
+ cpufreq_cpu_put(policy);
+ }
+
+-static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
++static int cpufreq_stats_update_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 i, j, count = 0;
+ 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;
++ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
+
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ unsigned int freq = table[i].frequency;
+@@ -223,40 +196,76 @@ static int cpufreq_stats_create_table(st
+ count++;
+ }
+
++ if (stat->max_state != count) {
++ stat->max_state = count;
++ kfree(stat->time_in_state);
++ stat->time_in_state = NULL;
++ }
++
+ 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);
+-
++ if (stat->time_in_state) {
++ memset(stat->time_in_state, 0, alloc_size);
++ } else {
++ stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
++ if (!stat->time_in_state)
++ return -ENOMEM;
++ stat->freq_table = (unsigned int *)(
++ stat->time_in_state + count);
+ #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+- stat->trans_table = stat->freq_table + count;
++ 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;
++ if (stat->freq_table) {
++ 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);
++ return 0;
++}
++
++static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
++ struct cpufreq_frequency_table *table)
++{
++ unsigned int ret = 0;
++ struct cpufreq_stats *stat;
++ struct cpufreq_policy *data;
++ unsigned int cpu = policy->cpu;
++
++ 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_out;
++ }
++ ret = sysfs_create_group(&data->kobj, &stats_attr_group);
+ cpufreq_cpu_put(data);
++ if (ret)
++ goto error_out;
++
++ stat->cpu = cpu;
++ per_cpu(cpufreq_stats_table, cpu) = stat;
++
+ return 0;
+ error_out:
+- cpufreq_cpu_put(data);
+-error_get_fail:
+ kfree(stat);
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
+ return ret;
+@@ -274,10 +283,12 @@ static int cpufreq_stat_notifier_policy(
+ table = cpufreq_frequency_get_table(cpu);
+ if (!table)
+ return 0;
+- ret = cpufreq_stats_create_table(policy, table);
+- if (ret)
+- return ret;
+- return 0;
++ if (!per_cpu(cpufreq_stats_table, cpu)) {
++ ret = cpufreq_stats_create_table(policy, table);
++ if (ret)
++ return ret;
++ }
++ return cpufreq_stats_update_table(policy, table);
+ }
+
+ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
+@@ -297,21 +308,23 @@ static int cpufreq_stat_notifier_trans(s
+ old_index = stat->last_index;
+ new_index = freq_table_get_index(stat, freq->new);
+
+- /* We can't do stat->time_in_state[-1]= .. */
+- if (old_index == -1 || new_index == -1)
+- return 0;
+-
+ cpufreq_stats_update(freq->cpu);
+-
+ if (old_index == new_index)
+ return 0;
+
++ if (new_index == -1)
++ return 0;
++
+ spin_lock(&cpufreq_stats_lock);
+ stat->last_index = new_index;
++ if (old_index != -1) {
+ #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+- stat->trans_table[old_index * stat->max_state + new_index]++;
++ if (stat->trans_table)
++ stat->trans_table[old_index * stat->max_state +
++ new_index]++;
+ #endif
+- stat->total_trans++;
++ stat->total_trans++;
++ }
+ spin_unlock(&cpufreq_stats_lock);
+ return 0;
+ }
+@@ -327,10 +340,6 @@ static int __cpuinit cpufreq_stat_cpu_ca
+ case CPU_ONLINE_FROZEN:
+ cpufreq_update_policy(cpu);
+ break;
+- case CPU_DOWN_PREPARE:
+- case CPU_DOWN_PREPARE_FROZEN:
+- cpufreq_stats_free_sysfs(cpu);
+- break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ cpufreq_stats_free_table(cpu);
+@@ -339,10 +348,9 @@ static int __cpuinit cpufreq_stat_cpu_ca
+ return NOTIFY_OK;
+ }
+
+-/* priority=1 so this will get called before cpufreq_remove_dev */
+-static struct notifier_block cpufreq_stat_cpu_notifier __refdata = {
++static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
++{
+ .notifier_call = cpufreq_stat_cpu_callback,
+- .priority = 1,
+ };
+
+ static struct notifier_block notifier_policy_block = {
+@@ -392,7 +400,6 @@ static void __exit cpufreq_stats_exit(vo
+ unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+ for_each_online_cpu(cpu) {
+ cpufreq_stats_free_table(cpu);
+- cpufreq_stats_free_sysfs(cpu);
+ }
+ }
+