Commit e8990100 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-dj.bkbits.net/cpufreq

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 8a6d2688 885d5a1d
...@@ -336,9 +336,10 @@ config ZBOOT_ROM_BSS ...@@ -336,9 +336,10 @@ config ZBOOT_ROM_BSS
while the decompressor is running. Unless you have special requirements, while the decompressor is running. Unless you have special requirements,
you should not change this value. you should not change this value.
if (ARCH_SA1100 || ARCH_INTEGRATOR)
config CPU_FREQ config CPU_FREQ
bool "Support CPU clock change (EXPERIMENTAL)" bool "Support CPU clock change"
depends on (ARCH_SA1100 || ARCH_INTEGRATOR) && EXPERIMENTAL
help help
CPU clock scaling allows you to change the clock speed of the CPU clock scaling allows you to change the clock speed of the
running CPU on the fly. This is a nice method to save battery power, running CPU on the fly. This is a nice method to save battery power,
...@@ -348,20 +349,17 @@ config CPU_FREQ ...@@ -348,20 +349,17 @@ config CPU_FREQ
written) to implement the policy. If you don't understand what this written) to implement the policy. If you don't understand what this
is all about, it's safe to say 'N'. is all about, it's safe to say 'N'.
source "drivers/cpufreq/Kconfig"
# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor
config CPU_FREQ_SA1100 config CPU_FREQ_SA1100
bool bool
depends on CPU_FREQ && SA1100_LART depends on CPU_FREQ && SA1100_LART
default y default y
select CPU_FREQ_24_API if SYSCTL
config CPU_FREQ_SA1110 config CPU_FREQ_SA1110
bool bool
depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
default y default y
select CPU_FREQ_24_API if SYSCTL
config CPU_FREQ_INTEGRATOR config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs" tristate "CPUfreq driver for ARM Integrator CPUs"
...@@ -374,10 +372,6 @@ config CPU_FREQ_INTEGRATOR ...@@ -374,10 +372,6 @@ config CPU_FREQ_INTEGRATOR
If in doubt, say Y. If in doubt, say Y.
if (CPU_FREQ_INTEGRATOR) || (CPU_FREQ_SA1110) || (CPU_FREQ_SA1100)
source "drivers/cpufreq/Kconfig"
endif endif
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
......
...@@ -42,16 +42,6 @@ config X86_ACPI_CPUFREQ ...@@ -42,16 +42,6 @@ config X86_ACPI_CPUFREQ
If in doubt, say N. If in doubt, say N.
config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on X86_ACPI_CPUFREQ && PROC_FS
help
This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic,
cross-architecture cpufreq interfaces should be used.
If in doubt, say N.
config ELAN_CPUFREQ config ELAN_CPUFREQ
tristate "AMD Elan" tristate "AMD Elan"
depends on CPU_FREQ_TABLE && X86_ELAN depends on CPU_FREQ_TABLE && X86_ELAN
...@@ -95,7 +85,7 @@ config X86_POWERNOW_K7_ACPI ...@@ -95,7 +85,7 @@ config X86_POWERNOW_K7_ACPI
config X86_POWERNOW_K8 config X86_POWERNOW_K8
tristate "AMD Opteron/Athlon64 PowerNow!" tristate "AMD Opteron/Athlon64 PowerNow!"
depends on CPU_FREQ && EXPERIMENTAL depends on CPU_FREQ_TABLE && EXPERIMENTAL
help help
This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors. This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
...@@ -122,29 +112,40 @@ config X86_GX_SUSPMOD ...@@ -122,29 +112,40 @@ config X86_GX_SUSPMOD
config X86_SPEEDSTEP_CENTRINO config X86_SPEEDSTEP_CENTRINO
tristate "Intel Enhanced SpeedStep" tristate "Intel Enhanced SpeedStep"
depends on CPU_FREQ_TABLE depends on CPU_FREQ_TABLE
select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
help help
This adds the CPUFreq driver for Enhanced SpeedStep enabled This adds the CPUFreq driver for Enhanced SpeedStep enabled
mobile CPUs. This means Intel Pentium M (Centrino) CPUs. mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
you also need to say Y to "Use ACPI tables to decode..." below
[which might imply enabling ACPI] if you want to use this driver
on non-Banias CPUs.
For details, take a look at <file:Documentation/cpu-freq/>. For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N. If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO_TABLE
bool
depends on X86_SPEEDSTEP_CENTRINO
default y
config X86_SPEEDSTEP_CENTRINO_ACPI config X86_SPEEDSTEP_CENTRINO_ACPI
bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)" bool "Use ACPI tables to decode valid frequency/voltage pairs"
depends on EXPERIMENTAL depends on X86_SPEEDSTEP_CENTRINO
depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y")) depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
default y
help help
Use primarily the information provided in the BIOS ACPI tables Use primarily the information provided in the BIOS ACPI tables
to determine valid CPU frequency and voltage pairings. to determine valid CPU frequency and voltage pairings. It is
required for the driver to work on non-Banias CPUs.
If in doubt, say Y. If in doubt, say Y.
config X86_SPEEDSTEP_CENTRINO_TABLE
bool "Built-in tables for Banias CPUs"
depends on X86_SPEEDSTEP_CENTRINO
default y
help
Use built-in tables for Banias CPUs if ACPI encoding
is not available.
If in doubt, say N.
config X86_SPEEDSTEP_ICH config X86_SPEEDSTEP_ICH
tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
depends on CPU_FREQ_TABLE depends on CPU_FREQ_TABLE
...@@ -181,21 +182,6 @@ config X86_P4_CLOCKMOD ...@@ -181,21 +182,6 @@ config X86_P4_CLOCKMOD
If in doubt, say N. If in doubt, say N.
config X86_SPEEDSTEP_LIB
tristate
depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
help
Don't perform all checks for a speedstep capable system which would
normally be done. Some ancient or strange systems, though speedstep
capable, don't always indicate that they are speedstep capable. This
option let's the probing code bypass some of those checks if the
parameter "relaxed_check=1" is passed to the module.
config X86_LONGRUN config X86_LONGRUN
tristate "Transmeta LongRun" tristate "Transmeta LongRun"
depends on CPU_FREQ depends on CPU_FREQ
...@@ -219,4 +205,34 @@ config X86_LONGHAUL ...@@ -219,4 +205,34 @@ config X86_LONGHAUL
If in doubt, say N. If in doubt, say N.
comment "shared options"
depends on CPU_FREQ
config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS
depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
help
This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic,
cross-architecture cpufreq interfaces should be used.
If in doubt, say N.
config X86_SPEEDSTEP_LIB
tristate
depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
help
Don't perform all checks for a speedstep capable system which would
normally be done. Some ancient or strange systems, though speedstep
capable, don't always indicate that they are speedstep capable. This
option lets the probing code bypass some of those checks if the
parameter "relaxed_check=1" is passed to the module.
endmenu endmenu
...@@ -110,7 +110,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, ...@@ -110,7 +110,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
{ {
unsigned int newstate = DC_RESV; unsigned int newstate = DC_RESV;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
cpumask_t cpus_allowed, affected_cpu_map; cpumask_t cpus_allowed;
int i; int i;
if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate)) if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
...@@ -122,18 +122,8 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, ...@@ -122,18 +122,8 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
if (freqs.new == freqs.old) if (freqs.new == freqs.old)
return 0; return 0;
/* switch to physical CPU where state is to be changed*/
cpus_allowed = current->cpus_allowed;
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[policy->cpu];
#else
affected_cpu_map = cpumask_of_cpu(policy->cpu);
#endif
/* notifiers */ /* notifiers */
for_each_cpu_mask(i, affected_cpu_map) { for_each_cpu_mask(i, policy->cpus) {
freqs.cpu = i; freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
} }
...@@ -141,7 +131,9 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, ...@@ -141,7 +131,9 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
* Developer's Manual, Volume 3 * Developer's Manual, Volume 3
*/ */
for_each_cpu_mask(i, affected_cpu_map) { cpus_allowed = current->cpus_allowed;
for_each_cpu_mask(i, policy->cpus) {
cpumask_t this_cpu = cpumask_of_cpu(i); cpumask_t this_cpu = cpumask_of_cpu(i);
set_cpus_allowed(current, this_cpu); set_cpus_allowed(current, this_cpu);
...@@ -152,7 +144,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, ...@@ -152,7 +144,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
set_cpus_allowed(current, cpus_allowed); set_cpus_allowed(current, cpus_allowed);
/* notifiers */ /* notifiers */
for_each_cpu_mask(i, affected_cpu_map) { for_each_cpu_mask(i, policy->cpus) {
freqs.cpu = i; freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
} }
...@@ -219,6 +211,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -219,6 +211,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
int cpuid = 0; int cpuid = 0;
unsigned int i; unsigned int i;
#ifdef CONFIG_SMP
policy->cpus = cpu_sibling_map[policy->cpu];
#endif
/* Errata workaround */ /* Errata workaround */
cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
switch (cpuid) { switch (cpuid) {
...@@ -260,14 +256,13 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) ...@@ -260,14 +256,13 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
static unsigned int cpufreq_p4_get(unsigned int cpu) static unsigned int cpufreq_p4_get(unsigned int cpu)
{ {
cpumask_t cpus_allowed, affected_cpu_map; cpumask_t cpus_allowed;
u32 l, h; u32 l, h;
cpus_allowed = current->cpus_allowed; cpus_allowed = current->cpus_allowed;
affected_cpu_map = cpumask_of_cpu(cpu);
set_cpus_allowed(current, affected_cpu_map); set_cpus_allowed(current, cpumask_of_cpu(cpu));
BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map)); BUG_ON(smp_processor_id() != cpu);
rdmsr(MSR_IA32_THERM_CONTROL, l, h); rdmsr(MSR_IA32_THERM_CONTROL, l, h);
...@@ -335,4 +330,3 @@ MODULE_LICENSE ("GPL"); ...@@ -335,4 +330,3 @@ MODULE_LICENSE ("GPL");
late_initcall(cpufreq_p4_init); late_initcall(cpufreq_p4_init);
module_exit(cpufreq_p4_exit); module_exit(cpufreq_p4_exit);
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define PFX "powernow-k8: " #define PFX "powernow-k8: "
#define BFX PFX "BIOS error: " #define BFX PFX "BIOS error: "
#define VERSION "version 1.00.09b" #define VERSION "version 1.00.09e"
#include "powernow-k8.h" #include "powernow-k8.h"
/* serialize freq changes */ /* serialize freq changes */
...@@ -596,6 +596,8 @@ static int find_psb_table(struct powernow_k8_data *data) ...@@ -596,6 +596,8 @@ static int find_psb_table(struct powernow_k8_data *data)
unsigned int i; unsigned int i;
u32 mvs; u32 mvs;
u8 maxvid; u8 maxvid;
u32 cpst = 0;
u32 thiscpuid;
for (i = 0xc0000; i < 0xffff0; i += 0x10) { for (i = 0xc0000; i < 0xffff0; i += 0x10) {
/* Scan BIOS looking for the signature. */ /* Scan BIOS looking for the signature. */
...@@ -634,7 +636,14 @@ static int find_psb_table(struct powernow_k8_data *data) ...@@ -634,7 +636,14 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk(KERN_INFO PFX "maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs); dprintk(KERN_INFO PFX "maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs);
dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst); dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst);
if (psb->numpst != 1) { cpst = psb->numpst;
if ((psb->cpuid == 0x00000fc0) || (psb->cpuid == 0x00000fe0) ){
thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
if ((thiscpuid == 0x00000fc0) || (thiscpuid == 0x00000fe0) ) {
cpst = 1;
}
}
if (cpst != 1) {
printk(KERN_ERR BFX "numpst must be 1\n"); printk(KERN_ERR BFX "numpst must be 1\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -77,7 +77,7 @@ static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_ ...@@ -77,7 +77,7 @@ static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_
/* Operating points for current CPU */ /* Operating points for current CPU */
static struct cpu_model *centrino_model; static struct cpu_model *centrino_model;
static int centrino_cpu; static const struct cpu_id *centrino_cpu;
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
...@@ -289,7 +289,9 @@ static unsigned extract_clock(unsigned msr) ...@@ -289,7 +289,9 @@ static unsigned extract_clock(unsigned msr)
* for centrino, as some DSDTs are buggy. * for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure. * Ideally, this can be done using the acpi_data structure.
*/ */
if (centrino_cpu) { if ((centrino_cpu == &cpu_ids[CPU_BANIAS]) ||
(centrino_cpu == &cpu_ids[CPU_DOTHAN_A1]) ||
(centrino_cpu == &cpu_ids[CPU_DOTHAN_B0])) {
msr = (msr >> 8) & 0xff; msr = (msr >> 8) & 0xff;
return msr * 100000; return msr * 100000;
} }
...@@ -457,7 +459,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -457,7 +459,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
break; break;
if (i != N_IDS) if (i != N_IDS)
centrino_cpu = 1; centrino_cpu = &cpu_ids[i];
if (centrino_cpu_init_acpi(policy)) { if (centrino_cpu_init_acpi(policy)) {
if (policy->cpu != 0) if (policy->cpu != 0)
...@@ -567,7 +569,7 @@ static int centrino_target (struct cpufreq_policy *policy, ...@@ -567,7 +569,7 @@ static int centrino_target (struct cpufreq_policy *policy,
* Make sure we are running on the CPU that wants to change frequency * Make sure we are running on the CPU that wants to change frequency
*/ */
saved_mask = current->cpus_allowed; saved_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(policy->cpu)); set_cpus_allowed(current, policy->cpus);
if (smp_processor_id() != policy->cpu) { if (smp_processor_id() != policy->cpu) {
return(-EAGAIN); return(-EAGAIN);
} }
......
...@@ -223,24 +223,23 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -223,24 +223,23 @@ static unsigned int speedstep_detect_chipset (void)
return 0; return 0;
} }
static unsigned int speedstep_get(unsigned int cpu) static unsigned int _speedstep_get(cpumask_t cpus)
{ {
unsigned int speed; unsigned int speed;
cpumask_t cpus_allowed,affected_cpu_map; cpumask_t cpus_allowed;
/* only run on CPU to be set, or on its sibling */
cpus_allowed = current->cpus_allowed; cpus_allowed = current->cpus_allowed;
#ifdef CONFIG_SMP set_cpus_allowed(current, cpus);
affected_cpu_map = cpu_sibling_map[cpu]; speed = speedstep_get_processor_frequency(speedstep_processor);
#else
affected_cpu_map = cpumask_of_cpu(cpu);
#endif
set_cpus_allowed(current, affected_cpu_map);
speed=speedstep_get_processor_frequency(speedstep_processor);
set_cpus_allowed(current, cpus_allowed); set_cpus_allowed(current, cpus_allowed);
return speed; return speed;
} }
static unsigned int speedstep_get(unsigned int cpu)
{
return _speedstep_get(cpumask_of_cpu(cpu));
}
/** /**
* speedstep_target - set a new CPUFreq policy * speedstep_target - set a new CPUFreq policy
* @policy: new policy * @policy: new policy
...@@ -255,13 +254,13 @@ static int speedstep_target (struct cpufreq_policy *policy, ...@@ -255,13 +254,13 @@ static int speedstep_target (struct cpufreq_policy *policy,
{ {
unsigned int newstate = 0; unsigned int newstate = 0;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
cpumask_t cpus_allowed, affected_cpu_map; cpumask_t cpus_allowed;
int i; int i;
if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
return -EINVAL; return -EINVAL;
freqs.old = speedstep_get(policy->cpu); freqs.old = _speedstep_get(policy->cpus);
freqs.new = speedstep_freqs[newstate].frequency; freqs.new = speedstep_freqs[newstate].frequency;
freqs.cpu = policy->cpu; freqs.cpu = policy->cpu;
...@@ -271,27 +270,20 @@ static int speedstep_target (struct cpufreq_policy *policy, ...@@ -271,27 +270,20 @@ static int speedstep_target (struct cpufreq_policy *policy,
cpus_allowed = current->cpus_allowed; cpus_allowed = current->cpus_allowed;
/* only run on CPU to be set, or on its sibling */ for_each_cpu_mask(i, policy->cpus) {
#ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[policy->cpu];
#else
affected_cpu_map = cpumask_of_cpu(policy->cpu);
#endif
for_each_cpu_mask(i, affected_cpu_map) {
freqs.cpu = i; freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
} }
/* switch to physical CPU where state is to be changed */ /* switch to physical CPU where state is to be changed */
set_cpus_allowed(current, affected_cpu_map); set_cpus_allowed(current, policy->cpus);
speedstep_set_state(newstate); speedstep_set_state(newstate);
/* allow to be run on all CPUs */ /* allow to be run on all CPUs */
set_cpus_allowed(current, cpus_allowed); set_cpus_allowed(current, cpus_allowed);
for_each_cpu_mask(i, affected_cpu_map) { for_each_cpu_mask(i, policy->cpus) {
freqs.cpu = i; freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
} }
...@@ -317,21 +309,15 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -317,21 +309,15 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
{ {
int result = 0; int result = 0;
unsigned int speed; unsigned int speed;
cpumask_t cpus_allowed,affected_cpu_map; cpumask_t cpus_allowed;
/* capability check */
if (policy->cpu != 0) /* FIXME: better support for SMT in cpufreq core. Up until then, it's better to register only one CPU */
return -ENODEV;
/* only run on CPU to be set, or on its sibling */ /* only run on CPU to be set, or on its sibling */
cpus_allowed = current->cpus_allowed;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[policy->cpu]; policy->cpus = cpu_sibling_map[policy->cpu];
#else
affected_cpu_map = cpumask_of_cpu(policy->cpu);
#endif #endif
set_cpus_allowed(current, affected_cpu_map);
cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, policy->cpus);
/* detect low and high frequency */ /* detect low and high frequency */
result = speedstep_get_freqs(speedstep_processor, result = speedstep_get_freqs(speedstep_processor,
...@@ -343,7 +329,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -343,7 +329,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return result; return result;
/* get current speed setting */ /* get current speed setting */
speed = speedstep_get(policy->cpu); speed = _speedstep_get(policy->cpus);
if (!speed) if (!speed)
return -EIO; return -EIO;
......
...@@ -260,12 +260,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -260,12 +260,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
if (result) { if (result) {
/* fall back to speedstep_lib.c dection mechanism: try both states out */ /* fall back to speedstep_lib.c dection mechanism: try both states out */
dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n"); dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n");
if (!speedstep_processor)
speedstep_processor = speedstep_detect_processor();
if (!speedstep_processor)
return -ENODEV;
result = speedstep_get_freqs(speedstep_processor, result = speedstep_get_freqs(speedstep_processor,
&speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_LOW].frequency,
&speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
...@@ -310,10 +304,6 @@ static unsigned int speedstep_get(unsigned int cpu) ...@@ -310,10 +304,6 @@ static unsigned int speedstep_get(unsigned int cpu)
{ {
if (cpu) if (cpu)
return -ENODEV; return -ENODEV;
if (!speedstep_processor)
speedstep_processor = speedstep_detect_processor();
if (!speedstep_processor)
return 0;
return speedstep_get_processor_frequency(speedstep_processor); return speedstep_get_processor_frequency(speedstep_processor);
} }
...@@ -354,10 +344,19 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -354,10 +344,19 @@ static struct cpufreq_driver speedstep_driver = {
*/ */
static int __init speedstep_init(void) static int __init speedstep_init(void)
{ {
struct cpuinfo_x86 *c = cpu_data; speedstep_processor = speedstep_detect_processor();
switch (speedstep_processor) {
case SPEEDSTEP_PROCESSOR_PIII_T:
case SPEEDSTEP_PROCESSOR_PIII_C:
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
break;
default:
speedstep_processor = 0;
}
if (c->x86_vendor != X86_VENDOR_INTEL) { if (!speedstep_processor) {
printk (KERN_INFO PFX "No Intel CPU detected.\n"); dprintk (KERN_INFO PFX "No supported Intel CPU detected.\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -48,7 +48,7 @@ config X86_POWERNOW_K8_ACPI ...@@ -48,7 +48,7 @@ config X86_POWERNOW_K8_ACPI
config X86_SPEEDSTEP_CENTRINO config X86_SPEEDSTEP_CENTRINO
tristate "Intel Enhanced SpeedStep" tristate "Intel Enhanced SpeedStep"
depends on CPU_FREQ_TABLE depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
help help
This adds the CPUFreq driver for Enhanced SpeedStep enabled This adds the CPUFreq driver for Enhanced SpeedStep enabled
mobile CPUs. This means Intel Pentium M (Centrino) CPUs mobile CPUs. This means Intel Pentium M (Centrino) CPUs
...@@ -58,21 +58,11 @@ config X86_SPEEDSTEP_CENTRINO ...@@ -58,21 +58,11 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N. If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO_TABLE config X86_SPEEDSTEP_CENTRINO_ACPI
bool bool
depends on X86_SPEEDSTEP_CENTRINO depends on X86_SPEEDSTEP_CENTRINO
default y default y
config X86_SPEEDSTEP_CENTRINO_ACPI
bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)"
depends on EXPERIMENTAL
depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
help
Use primarily the information provided in the BIOS ACPI tables
to determine valid CPU frequency and voltage pairings.
If in doubt, say Y.
config X86_ACPI_CPUFREQ config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver" tristate "ACPI Processor P-States driver"
depends on CPU_FREQ_TABLE && ACPI_PROCESSOR depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
...@@ -84,9 +74,13 @@ config X86_ACPI_CPUFREQ ...@@ -84,9 +74,13 @@ config X86_ACPI_CPUFREQ
If in doubt, say N. If in doubt, say N.
comment "shared options"
depends on CPU_FREQ
config X86_ACPI_CPUFREQ_PROC_INTF config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)" bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on X86_ACPI_CPUFREQ && PROC_FS depends on PROC_FS
depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
help help
This enables the deprecated /proc/acpi/processor/../performance This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic, interface. While it is helpful for debugging, the generic,
......
...@@ -33,7 +33,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE ...@@ -33,7 +33,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
help help
Use the CPUFreq governor 'userspace' as default. This allows Use the CPUFreq governor 'userspace' as default. This allows
you to set the CPU frequency manually or when an userspace you to set the CPU frequency manually or when an userspace
programm shall be able to set the CPU dynamically without having program shall be able to set the CPU dynamically without having
to enable the userspace governor manually. to enable the userspace governor manually.
endchoice endchoice
...@@ -42,7 +42,7 @@ config CPU_FREQ_GOV_PERFORMANCE ...@@ -42,7 +42,7 @@ config CPU_FREQ_GOV_PERFORMANCE
tristate "'performance' governor" tristate "'performance' governor"
depends on CPU_FREQ depends on CPU_FREQ
help help
This cpufreq governors set the frequency statically to the This cpufreq governor sets the frequency statically to the
highest available CPU frequency. highest available CPU frequency.
If in doubt, say Y. If in doubt, say Y.
...@@ -51,7 +51,7 @@ config CPU_FREQ_GOV_POWERSAVE ...@@ -51,7 +51,7 @@ config CPU_FREQ_GOV_POWERSAVE
tristate "'powersave' governor" tristate "'powersave' governor"
depends on CPU_FREQ depends on CPU_FREQ
help help
Theis cpufreq governors set the frequency statically to the This cpufreq governor sets the frequency statically to the
lowest available CPU frequency. lowest available CPU frequency.
If in doubt, say Y. If in doubt, say Y.
...@@ -61,7 +61,7 @@ config CPU_FREQ_GOV_USERSPACE ...@@ -61,7 +61,7 @@ config CPU_FREQ_GOV_USERSPACE
depends on CPU_FREQ depends on CPU_FREQ
help help
Enable this cpufreq governor when you either want to set the Enable this cpufreq governor when you either want to set the
CPU frequency manually or when an userspace programm shall CPU frequency manually or when an userspace program shall
be able to set the CPU dynamically, like on LART be able to set the CPU dynamically, like on LART
<http://www.lart.tudelft.nl/> <http://www.lart.tudelft.nl/>
...@@ -69,6 +69,21 @@ config CPU_FREQ_GOV_USERSPACE ...@@ -69,6 +69,21 @@ config CPU_FREQ_GOV_USERSPACE
If in doubt, say Y. If in doubt, say Y.
config CPU_FREQ_24_API
bool "/proc/sys/cpu/ interface (2.4. / OLD)"
depends on CPU_FREQ_GOV_USERSPACE
depends on SYSCTL
help
This enables the /proc/sys/cpu/ sysctl interface for controlling
the CPUFreq,"userspace" governor. This is the same interface
as known from the 2.4.-kernel patches for CPUFreq, and offers
the same functionality as long as "userspace" is the
selected governor for the specified CPU.
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config CPU_FREQ_GOV_ONDEMAND config CPU_FREQ_GOV_ONDEMAND
tristate "'ondemand' cpufreq policy governor" tristate "'ondemand' cpufreq policy governor"
depends on CPU_FREQ depends on CPU_FREQ
...@@ -83,17 +98,3 @@ config CPU_FREQ_GOV_ONDEMAND ...@@ -83,17 +98,3 @@ config CPU_FREQ_GOV_ONDEMAND
For details, take a look at linux/Documentation/cpu-freq. For details, take a look at linux/Documentation/cpu-freq.
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_24_API
bool "/proc/sys/cpu/ interface (2.4. / OLD)"
depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
help
This enables the /proc/sys/cpu/ sysctl interface for controlling
the CPUFreq,"userspace" governor. This is the same interface
as known from the 2.4.-kernel patches for CPUFreq, and offers
the same functionality as long as "userspace" is the
selected governor for the specified CPU.
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
...@@ -33,6 +33,14 @@ static struct cpufreq_driver *cpufreq_driver; ...@@ -33,6 +33,14 @@ static struct cpufreq_driver *cpufreq_driver;
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED;
/* we keep a copy of all ->add'ed CPU's struct sys_device here;
* as it is only accessed in ->add and ->remove, no lock or reference
* count is necessary.
*/
static struct sys_device *cpu_sys_devices[NR_CPUS];
/* internal prototypes */ /* internal prototypes */
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static void handle_update(void *data); static void handle_update(void *data);
...@@ -154,6 +162,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) ...@@ -154,6 +162,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
*/ */
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((likely(cpufreq_cpu_data[freqs->cpu])) && if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
(likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) &&
(likely(cpufreq_cpu_data[freqs->cpu]->cur)) && (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
{ {
...@@ -168,7 +177,8 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) ...@@ -168,7 +177,8 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
if (likely(cpufreq_cpu_data[freqs->cpu])) if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
(likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)))
cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
break; break;
} }
...@@ -456,6 +466,18 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -456,6 +466,18 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
struct freq_attr **drv_attr; struct freq_attr **drv_attr;
unsigned long flags; unsigned long flags;
unsigned int j;
#ifdef CONFIG_SMP
/* check whether a different CPU already registered this
* CPU because it is in the same boat. */
policy = cpufreq_cpu_get(cpu);
if (unlikely(policy)) {
cpu_sys_devices[cpu] = sys_dev;
sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq");
return 0;
}
#endif
if (!try_module_get(cpufreq_driver->owner)) if (!try_module_get(cpufreq_driver->owner))
return -EINVAL; return -EINVAL;
...@@ -468,6 +490,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -468,6 +490,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
memset(policy, 0, sizeof(struct cpufreq_policy)); memset(policy, 0, sizeof(struct cpufreq_policy));
policy->cpu = cpu; policy->cpu = cpu;
policy->cpus = cpumask_of_cpu(cpu);
init_MUTEX_LOCKED(&policy->lock); init_MUTEX_LOCKED(&policy->lock);
init_completion(&policy->kobj_unregister); init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); INIT_WORK(&policy->update, handle_update, (void *)(long)cpu);
...@@ -502,7 +526,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -502,7 +526,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
spin_lock_irqsave(&cpufreq_driver_lock, flags); spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = policy; for_each_cpu_mask(j, policy->cpus)
cpufreq_cpu_data[j] = policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL; /* to assure that the starting sequence is policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */ * run in cpufreq_set_policy */
...@@ -515,12 +540,14 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ...@@ -515,12 +540,14 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
goto err_out_unregister; goto err_out_unregister;
module_put(cpufreq_driver->owner); module_put(cpufreq_driver->owner);
cpu_sys_devices[cpu] = sys_dev;
return 0; return 0;
err_out_unregister: err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags); spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = NULL; for_each_cpu_mask(j, policy->cpus)
cpufreq_cpu_data[j] = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
kobject_unregister(&policy->kobj); kobject_unregister(&policy->kobj);
...@@ -545,19 +572,69 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) ...@@ -545,19 +572,69 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
unsigned int cpu = sys_dev->id; unsigned int cpu = sys_dev->id;
unsigned long flags; unsigned long flags;
struct cpufreq_policy *data; struct cpufreq_policy *data;
#ifdef CONFIG_SMP
unsigned int j;
#endif
spin_lock_irqsave(&cpufreq_driver_lock, flags); spin_lock_irqsave(&cpufreq_driver_lock, flags);
data = cpufreq_cpu_data[cpu]; data = cpufreq_cpu_data[cpu];
if (!data) { if (!data) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
cpu_sys_devices[cpu] = NULL;
return -EINVAL; return -EINVAL;
} }
cpufreq_cpu_data[cpu] = NULL; cpufreq_cpu_data[cpu] = NULL;
#ifdef CONFIG_SMP
/* if this isn't the CPU which is the parent of the kobj, we
* only need to unlink, put and exit
*/
if (unlikely(cpu != data->cpu)) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
sysfs_remove_link(&sys_dev->kobj, "cpufreq");
cpu_sys_devices[cpu] = NULL;
cpufreq_cpu_put(data);
return 0;
}
#endif
if (!kobject_get(&data->kobj)) cpu_sys_devices[cpu] = NULL;
if (!kobject_get(&data->kobj)) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
return -EFAULT; return -EFAULT;
}
#ifdef CONFIG_SMP
/* if we have other CPUs still registered, we need to unlink them,
* or else wait_for_completion below will lock up. Clean the
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs
* links afterwards.
*/
if (unlikely(cpus_weight(data->cpus) > 1)) {
for_each_cpu_mask(j, data->cpus) {
if (j == cpu)
continue;
cpufreq_cpu_data[j] = NULL;
}
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (unlikely(cpus_weight(data->cpus) > 1)) {
for_each_cpu_mask(j, data->cpus) {
if (j == cpu)
continue;
sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq");
cpufreq_cpu_put(data);
}
}
#else
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
#endif
if (cpufreq_driver->target) if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP); __cpufreq_governor(data, CPUFREQ_GOV_STOP);
...@@ -676,6 +753,12 @@ static int cpufreq_resume(struct sys_device * sysdev) ...@@ -676,6 +753,12 @@ static int cpufreq_resume(struct sys_device * sysdev)
if (!cpu_policy) if (!cpu_policy)
return -EINVAL; return -EINVAL;
/* only handle each CPU group once */
if (unlikely(cpu_policy->cpu != cpu)) {
cpufreq_cpu_put(cpu_policy);
return 0;
}
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
unsigned int cur_freq = 0; unsigned int cur_freq = 0;
......
...@@ -515,7 +515,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, ...@@ -515,7 +515,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
switch (event) { switch (event) {
case CPUFREQ_GOV_START: case CPUFREQ_GOV_START:
if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE))) if (!cpu_online(cpu))
return -EINVAL; return -EINVAL;
BUG_ON(!policy->cur); BUG_ON(!policy->cur);
down(&userspace_sem); down(&userspace_sem);
...@@ -534,7 +534,6 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, ...@@ -534,7 +534,6 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
cpu_max_freq[cpu] = 0; cpu_max_freq[cpu] = 0;
sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
up(&userspace_sem); up(&userspace_sem);
module_put(THIS_MODULE);
break; break;
case CPUFREQ_GOV_LIMITS: case CPUFREQ_GOV_LIMITS:
down(&userspace_sem); down(&userspace_sem);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/cpumask.h>
#define CPUFREQ_NAME_LEN 16 #define CPUFREQ_NAME_LEN 16
...@@ -69,7 +70,8 @@ struct cpufreq_real_policy { ...@@ -69,7 +70,8 @@ struct cpufreq_real_policy {
}; };
struct cpufreq_policy { struct cpufreq_policy {
unsigned int cpu; /* cpu nr */ cpumask_t cpus; /* affected CPUs */
unsigned int cpu; /* cpu nr of registered CPU */
struct cpufreq_cpuinfo cpuinfo;/* see above */ struct cpufreq_cpuinfo cpuinfo;/* see above */
unsigned int min; /* in kHz */ unsigned int min; /* in kHz */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment