drivers: cpufreq: backport cpufreq_times from Exynos9820
This commit is contained in:
parent
dd6694e199
commit
632f7f6b83
5 changed files with 51 additions and 40 deletions
|
@ -37,14 +37,6 @@ config CPU_FREQ_STAT
|
||||||
|
|
||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
config CPU_FREQ_STAT_DETAILS
|
|
||||||
bool "CPU frequency transition statistics details"
|
|
||||||
depends on CPU_FREQ_STAT
|
|
||||||
help
|
|
||||||
Show detailed CPU frequency transition table in sysfs.
|
|
||||||
|
|
||||||
If in doubt, say N.
|
|
||||||
|
|
||||||
config CPU_FREQ_TIMES
|
config CPU_FREQ_TIMES
|
||||||
bool "CPU frequency time-in-state statistics"
|
bool "CPU frequency time-in-state statistics"
|
||||||
help
|
help
|
||||||
|
|
|
@ -24,9 +24,7 @@ struct cpufreq_stats {
|
||||||
unsigned int last_index;
|
unsigned int last_index;
|
||||||
u64 *time_in_state;
|
u64 *time_in_state;
|
||||||
unsigned int *freq_table;
|
unsigned int *freq_table;
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
|
||||||
unsigned int *trans_table;
|
unsigned int *trans_table;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cpufreq_stats_update(struct cpufreq_stats *stats)
|
static int cpufreq_stats_update(struct cpufreq_stats *stats)
|
||||||
|
@ -40,6 +38,16 @@ static int cpufreq_stats_update(struct cpufreq_stats *stats)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpufreq_stats_clear_table(struct cpufreq_stats *stats)
|
||||||
|
{
|
||||||
|
unsigned int count = stats->max_state;
|
||||||
|
|
||||||
|
memset(stats->time_in_state, 0, count * sizeof(u64));
|
||||||
|
memset(stats->trans_table, 0, count * count * sizeof(int));
|
||||||
|
stats->last_time = get_jiffies_64();
|
||||||
|
stats->total_trans = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
|
static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%d\n", policy->stats->total_trans);
|
return sprintf(buf, "%d\n", policy->stats->total_trans);
|
||||||
|
@ -63,7 +71,14 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
/* We don't care what is written to the attribute. */
|
||||||
|
cpufreq_stats_clear_table(policy->stats);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
||||||
{
|
{
|
||||||
struct cpufreq_stats *stats = policy->stats;
|
struct cpufreq_stats *stats = policy->stats;
|
||||||
|
@ -108,20 +123,19 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
cpufreq_freq_attr_ro(trans_table);
|
cpufreq_freq_attr_ro(trans_table);
|
||||||
#endif
|
|
||||||
|
|
||||||
cpufreq_freq_attr_ro(total_trans);
|
cpufreq_freq_attr_ro(total_trans);
|
||||||
cpufreq_freq_attr_ro(time_in_state);
|
cpufreq_freq_attr_ro(time_in_state);
|
||||||
|
cpufreq_freq_attr_wo(reset);
|
||||||
|
|
||||||
static struct attribute *default_attrs[] = {
|
static struct attribute *default_attrs[] = {
|
||||||
&total_trans.attr,
|
&total_trans.attr,
|
||||||
&time_in_state.attr,
|
&time_in_state.attr,
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
&reset.attr,
|
||||||
&trans_table.attr,
|
&trans_table.attr,
|
||||||
#endif
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static struct attribute_group stats_attr_group = {
|
static const struct attribute_group stats_attr_group = {
|
||||||
.attrs = default_attrs,
|
.attrs = default_attrs,
|
||||||
.name = "stats"
|
.name = "stats"
|
||||||
};
|
};
|
||||||
|
@ -156,11 +170,10 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||||
unsigned int i = 0, count = 0, ret = -ENOMEM;
|
unsigned int i = 0, count = 0, ret = -ENOMEM;
|
||||||
struct cpufreq_stats *stats;
|
struct cpufreq_stats *stats;
|
||||||
unsigned int alloc_size;
|
unsigned int alloc_size;
|
||||||
struct cpufreq_frequency_table *pos, *table;
|
struct cpufreq_frequency_table *pos;
|
||||||
|
|
||||||
/* We need cpufreq table for creating stats table */
|
count = cpufreq_table_count_valid_entries(policy);
|
||||||
table = policy->freq_table;
|
if (!count)
|
||||||
if (unlikely(!table))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* stats already initialized */
|
/* stats already initialized */
|
||||||
|
@ -171,15 +184,9 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Find total allocation size */
|
|
||||||
cpufreq_for_each_valid_entry(pos, table)
|
|
||||||
count++;
|
|
||||||
|
|
||||||
alloc_size = count * sizeof(int) + count * sizeof(u64);
|
alloc_size = count * sizeof(int) + count * sizeof(u64);
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
|
||||||
alloc_size += count * count * sizeof(int);
|
alloc_size += count * count * sizeof(int);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Allocate memory for time_in_state/freq_table/trans_table in one go */
|
/* Allocate memory for time_in_state/freq_table/trans_table in one go */
|
||||||
stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
|
stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
|
||||||
|
@ -188,14 +195,12 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
stats->freq_table = (unsigned int *)(stats->time_in_state + count);
|
stats->freq_table = (unsigned int *)(stats->time_in_state + count);
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
|
||||||
stats->trans_table = stats->freq_table + count;
|
stats->trans_table = stats->freq_table + count;
|
||||||
#endif
|
|
||||||
|
|
||||||
stats->max_state = count;
|
stats->max_state = count;
|
||||||
|
|
||||||
/* Find valid-unique entries */
|
/* Find valid-unique entries */
|
||||||
cpufreq_for_each_valid_entry(pos, table)
|
cpufreq_for_each_valid_entry(pos, policy->freq_table)
|
||||||
if (freq_table_get_index(stats, pos->frequency) == -1)
|
if (freq_table_get_index(stats, pos->frequency) == -1)
|
||||||
stats->freq_table[i++] = pos->frequency;
|
stats->freq_table[i++] = pos->frequency;
|
||||||
|
|
||||||
|
@ -236,8 +241,6 @@ void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
|
||||||
cpufreq_stats_update(stats);
|
cpufreq_stats_update(stats);
|
||||||
|
|
||||||
stats->last_index = new_index;
|
stats->last_index = new_index;
|
||||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
|
||||||
stats->trans_table[old_index * stats->max_state + new_index]++;
|
stats->trans_table[old_index * stats->max_state + new_index]++;
|
||||||
#endif
|
|
||||||
stats->total_trans++;
|
stats->total_trans++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/cpufreq_times.h>
|
#include <linux/cpufreq_times.h>
|
||||||
#include <linux/cputime.h>
|
|
||||||
#include <linux/hashtable.h>
|
#include <linux/hashtable.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
@ -155,7 +155,7 @@ static int single_uid_time_in_state_show(struct seq_file *m, void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < uid_entry->max_state; ++i) {
|
for (i = 0; i < uid_entry->max_state; ++i) {
|
||||||
u64 time = cputime_to_clock_t(uid_entry->time_in_state[i]);
|
u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
|
||||||
seq_write(m, &time, sizeof(time));
|
seq_write(m, &time, sizeof(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,8 +215,7 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v)
|
||||||
seq_putc(m, ':');
|
seq_putc(m, ':');
|
||||||
}
|
}
|
||||||
for (i = 0; i < uid_entry->max_state; ++i) {
|
for (i = 0; i < uid_entry->max_state; ++i) {
|
||||||
u64 time =
|
u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
|
||||||
cputime_to_clock_t(uid_entry->time_in_state[i]);
|
|
||||||
seq_put_decimal_ull(m, " ", time);
|
seq_put_decimal_ull(m, " ", time);
|
||||||
}
|
}
|
||||||
if (uid_entry->max_state)
|
if (uid_entry->max_state)
|
||||||
|
@ -242,7 +241,7 @@ static int concurrent_time_seq_show(struct seq_file *m, void *v,
|
||||||
seq_putc(m, ':');
|
seq_putc(m, ':');
|
||||||
|
|
||||||
for (i = 0; i < num_possible_cpus; ++i) {
|
for (i = 0; i < num_possible_cpus; ++i) {
|
||||||
u64 time = cputime_to_clock_t(atomic64_read(×[i]));
|
u64 time = nsec_to_clock_t(atomic64_read(×[i]));
|
||||||
|
|
||||||
seq_put_decimal_ull(m, " ", time);
|
seq_put_decimal_ull(m, " ", time);
|
||||||
}
|
}
|
||||||
|
@ -369,7 +368,7 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
|
||||||
struct pid *pid, struct task_struct *p)
|
struct pid *pid, struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned int cpu, i;
|
unsigned int cpu, i;
|
||||||
cputime_t cputime;
|
u64 cputime;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct cpu_freqs *freqs;
|
struct cpu_freqs *freqs;
|
||||||
struct cpu_freqs *last_freqs = NULL;
|
struct cpu_freqs *last_freqs = NULL;
|
||||||
|
@ -388,14 +387,14 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
|
||||||
p->time_in_state)
|
p->time_in_state)
|
||||||
cputime = p->time_in_state[freqs->offset + i];
|
cputime = p->time_in_state[freqs->offset + i];
|
||||||
seq_printf(m, "%u %lu\n", freqs->freq_table[i],
|
seq_printf(m, "%u %lu\n", freqs->freq_table[i],
|
||||||
(unsigned long)cputime_to_clock_t(cputime));
|
(unsigned long)nsec_to_clock_t(cputime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
|
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpufreq_acct_update_power(struct task_struct *p, cputime_t cputime)
|
void cpufreq_acct_update_power(struct task_struct *p, u64 cputime)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
|
|
@ -238,6 +238,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
|
||||||
static struct freq_attr _name = \
|
static struct freq_attr _name = \
|
||||||
__ATTR(_name, 0644, show_##_name, store_##_name)
|
__ATTR(_name, 0644, show_##_name, store_##_name)
|
||||||
|
|
||||||
|
#define cpufreq_freq_attr_wo(_name) \
|
||||||
|
static struct freq_attr _name = \
|
||||||
|
__ATTR(_name, 0200, NULL, store_##_name)
|
||||||
|
|
||||||
#define define_one_global_ro(_name) \
|
#define define_one_global_ro(_name) \
|
||||||
static struct kobj_attribute _name = \
|
static struct kobj_attribute _name = \
|
||||||
__ATTR(_name, 0444, show_##_name, NULL)
|
__ATTR(_name, 0444, show_##_name, NULL)
|
||||||
|
@ -891,6 +895,20 @@ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy *policy)
|
||||||
|
{
|
||||||
|
struct cpufreq_frequency_table *pos;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (unlikely(!policy->freq_table))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cpufreq_for_each_valid_entry(pos, policy->freq_table)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
static inline int cpufreq_boost_trigger_state(int state)
|
static inline int cpufreq_boost_trigger_state(int state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#define _LINUX_CPUFREQ_TIMES_H
|
#define _LINUX_CPUFREQ_TIMES_H
|
||||||
|
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/cputime.h>
|
|
||||||
#include <linux/pid.h>
|
#include <linux/pid.h>
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_FREQ_TIMES
|
#ifdef CONFIG_CPU_FREQ_TIMES
|
||||||
|
@ -26,7 +25,7 @@ void cpufreq_task_times_alloc(struct task_struct *p);
|
||||||
void cpufreq_task_times_exit(struct task_struct *p);
|
void cpufreq_task_times_exit(struct task_struct *p);
|
||||||
int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
|
int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
|
||||||
struct pid *pid, struct task_struct *p);
|
struct pid *pid, struct task_struct *p);
|
||||||
void cpufreq_acct_update_power(struct task_struct *p, cputime_t cputime);
|
void cpufreq_acct_update_power(struct task_struct *p, u64 cputime);
|
||||||
void cpufreq_times_create_policy(struct cpufreq_policy *policy);
|
void cpufreq_times_create_policy(struct cpufreq_policy *policy);
|
||||||
void cpufreq_times_record_transition(struct cpufreq_policy *policy,
|
void cpufreq_times_record_transition(struct cpufreq_policy *policy,
|
||||||
unsigned int new_freq);
|
unsigned int new_freq);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue