From e8628dd06d66f2e3965ec9742029b401d63434f1 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 18 Apr 2008 13:31:12 -0700 Subject: [CPUFREQ] expose cpufreq coordination requirements regardless of coordination mechanism Currently, affected_cpus shows which CPUs need to have their frequency coordinated in software. When hardware coordination is in use, the contents of this file appear the same as when no coordination is required. This can lead to some confusion among user-space programs, for example, that do not know that extra coordination is required to force a CPU core to a particular speed to control power consumption. To fix this, create a "related_cpus" attribute that always displays the coordination map regardless of whatever coordination strategy the cpufreq driver uses (sw or hw). If the cpufreq driver does not provide a value, fall back to policy->cpus. Signed-off-by: Darrick J. Wong Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 1 + drivers/cpufreq/cpufreq.c | 29 ++++++++++++++++++++++++----- include/linux/cpufreq.h | 3 ++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 8db8f73503b..b0c8208df9f 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -601,6 +601,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { policy->cpus = perf->shared_cpu_map; } + policy->related_cpus = perf->shared_cpu_map; #ifdef CONFIG_SMP dmi_check_system(sw_any_bug_dmi_table); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d3575f5ec6d..7fce038fa57 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -583,15 +583,13 @@ out: i += sprintf(&buf[i], "\n"); return i; } -/** - * show_affected_cpus - show the CPUs affected by each transition - */ -static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) + +static ssize_t show_cpus(cpumask_t mask, char *buf) { ssize_t i = 0; unsigned int cpu; - for_each_cpu_mask(cpu, policy->cpus) { + for_each_cpu_mask(cpu, mask) { if (i) i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " "); i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu); @@ -602,6 +600,25 @@ static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) return i; } +/** + * show_related_cpus - show the CPUs affected by each transition even if + * hw coordination is in use + */ +static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) +{ + if (cpus_empty(policy->related_cpus)) + return show_cpus(policy->cpus, buf); + return show_cpus(policy->related_cpus, buf); +} + +/** + * show_affected_cpus - show the CPUs affected by each transition + */ +static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) +{ + return show_cpus(policy->cpus, buf); +} + static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, const char *buf, size_t count) { @@ -646,6 +663,7 @@ define_one_ro(cpuinfo_max_freq); define_one_ro(scaling_available_governors); define_one_ro(scaling_driver); define_one_ro(scaling_cur_freq); +define_one_ro(related_cpus); define_one_ro(affected_cpus); define_one_rw(scaling_min_freq); define_one_rw(scaling_max_freq); @@ -658,6 +676,7 @@ static struct attribute *default_attrs[] = { &scaling_min_freq.attr, &scaling_max_freq.attr, &affected_cpus.attr, + &related_cpus.attr, &scaling_governor.attr, &scaling_driver.attr, &scaling_available_governors.attr, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index ddd8652fc3f..a881fd62c44 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -83,7 +83,8 @@ struct cpufreq_real_policy { }; struct cpufreq_policy { - cpumask_t cpus; /* affected CPUs */ + cpumask_t cpus; /* CPUs requiring sw coordination */ + cpumask_t related_cpus; /* CPUs with any coordination */ unsigned int shared_type; /* ANY or ALL affected CPUs should set cpufreq */ unsigned int cpu; /* cpu nr of registered CPU */ -- cgit v1.2.3 From 605400a8ab44131698b206cbe253e48380daaa69 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 18 Apr 2008 13:31:13 -0700 Subject: [CPUFREQ] document the currently undocumented parts of the sysfs interface There is a description of some of the sysfs files. However, there are some that are not mentioned in the documentation, so add them to the user's guide. Signed-off-by: Darrick J. Wong Cc: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- Documentation/cpu-freq/user-guide.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index af3b925ece0..6c442d8426b 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -154,6 +154,11 @@ scaling_governor, and by "echoing" the name of another that some governors won't load - they only work on some specific architectures or processors. + +cpuinfo_cur_freq : Current speed of the CPU, in KHz. + +scaling_available_frequencies : List of available frequencies, in KHz. + scaling_min_freq and scaling_max_freq show the current "policy limits" (in kHz). By echoing new values into these @@ -162,6 +167,15 @@ scaling_max_freq show the current "policy limits" (in first set scaling_max_freq, then scaling_min_freq. +affected_cpus : List of CPUs that require software coordination + of frequency. + +related_cpus : List of CPUs that need some sort of frequency + coordination, whether software or hardware. + +scaling_driver : Hardware driver for cpufreq. + +scaling_cur_freq : Current frequency of the CPU, in KHz. If you have selected the "userspace" governor which allows you to set the CPU operating frequency to a specific value, you can read out -- cgit v1.2.3 From 30d221db4439973076953e2ed44344fa92d1d09f Mon Sep 17 00:00:00 2001 From: Alessandro Guido Date: Fri, 18 Apr 2008 13:31:13 -0700 Subject: [CPUFREQ] allow use of the powersave governor as the default one Allow use of the powersave cpufreq governor as the default one for EMBEDDED configs. Signed-off-by: Alessandro Guido Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- drivers/cpufreq/Kconfig | 9 +++++++++ drivers/cpufreq/cpufreq_powersave.c | 8 ++++++-- include/linux/cpufreq.h | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index c159ae64eeb..5f076aef74f 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -69,6 +69,15 @@ config CPU_FREQ_DEFAULT_GOV_PERFORMANCE the frequency statically to the highest frequency supported by the CPU. +config CPU_FREQ_DEFAULT_GOV_POWERSAVE + bool "powersave" + depends on EMBEDDED + select CPU_FREQ_GOV_POWERSAVE + help + Use the CPUFreq governor 'powersave' as default. This sets + the frequency statically to the lowest frequency supported by + the CPU. + config CPU_FREQ_DEFAULT_GOV_USERSPACE bool "userspace" select CPU_FREQ_GOV_USERSPACE diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index 13fe06b94b0..88d2f44fba4 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -35,12 +35,12 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, return 0; } -static struct cpufreq_governor cpufreq_gov_powersave = { +struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, .owner = THIS_MODULE, }; - +EXPORT_SYMBOL(cpufreq_gov_powersave); static int __init cpufreq_gov_powersave_init(void) { @@ -58,5 +58,9 @@ MODULE_AUTHOR("Dominik Brodowski "); MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +fs_initcall(cpufreq_gov_powersave_init); +#else module_init(cpufreq_gov_powersave_init); +#endif module_exit(cpufreq_gov_powersave_exit); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a881fd62c44..e7e91dbfde0 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -308,6 +308,9 @@ extern struct cpufreq_governor cpufreq_gov_performance; #endif #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance) +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE) +extern struct cpufreq_governor cpufreq_gov_powersave; +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave) #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) extern struct cpufreq_governor cpufreq_gov_userspace; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace) -- cgit v1.2.3 From 6501faf8c1bbaa51dc493f3681df016d2ebce833 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sun, 27 Apr 2008 13:46:56 -0700 Subject: [CPUFREQ] state info wrong after resume Sometimes old_index != stat->last_index, see cpufreq_update_policy, bios can change cpu setting in resume. In my test, after resume cpu is in lowest speed, but the stat info shows cpu is in full speed. This patch makes the stat info correct after a resume. Signed-off-by: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index ef09e069433..ae70d63a8b2 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -288,7 +288,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, if (!stat) return 0; - old_index = freq_table_get_index(stat, freq->old); + old_index = stat->last_index; new_index = freq_table_get_index(stat, freq->new); cpufreq_stats_update(freq->cpu); -- cgit v1.2.3