Commit 26a9b9cf 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 f9ee7122 a0dea52b
...@@ -88,6 +88,11 @@ config X86_POWERNOW_K7 ...@@ -88,6 +88,11 @@ config X86_POWERNOW_K7
If in doubt, say N. If in doubt, say N.
config X86_POWERNOW_K7_ACPI
bool
depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))
default y
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 && EXPERIMENTAL
...@@ -98,6 +103,11 @@ config X86_POWERNOW_K8 ...@@ -98,6 +103,11 @@ config X86_POWERNOW_K8
If in doubt, say N. If in doubt, say N.
config X86_POWERNOW_K8_ACPI
bool
depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
default y
config X86_GX_SUSPMOD config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
depends on CPU_FREQ depends on CPU_FREQ
......
...@@ -297,6 +297,7 @@ static void gx_set_cpuspeed(unsigned int khz) ...@@ -297,6 +297,7 @@ static void gx_set_cpuspeed(unsigned int khz)
case PCI_DEVICE_ID_CYRIX_5520: case PCI_DEVICE_ID_CYRIX_5520:
case PCI_DEVICE_ID_CYRIX_5510: case PCI_DEVICE_ID_CYRIX_5510:
suscfg = gx_params->pci_suscfg | SUSMOD; suscfg = gx_params->pci_suscfg | SUSMOD;
break;
default: default:
local_irq_restore(flags); local_irq_restore(flags);
dprintk("fatal: try to set unknown chipset.\n"); dprintk("fatal: try to set unknown chipset.\n");
......
...@@ -5,14 +5,19 @@ ...@@ -5,14 +5,19 @@
* Licensed under the terms of the GNU GPL License version 2. * Licensed under the terms of the GNU GPL License version 2.
* Based upon datasheets & sample CPUs kindly provided by VIA. * Based upon datasheets & sample CPUs kindly provided by VIA.
* *
* VIA have currently 2 different versions of Longhaul. * VIA have currently 3 different versions of Longhaul.
* Version 1 (Longhaul) uses the BCR2 MSR at 0x1147. * Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
* It is present only in Samuel 1, Samuel 2 and Ezra. * It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
* Version 2 (Powersaver) uses the POWERSAVER MSR at 0x110a. * Version 2 of longhaul is the same as v1, but adds voltage scaling.
* It is present in Ezra-T, Nehemiah and above. * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
* In addition to scaling multiplier, it can also scale voltage. * voltage scaling support has currently been disabled in this driver
* There is provision for scaling FSB too, but this doesn't work * until we have code that gets it right.
* too well in practice. * Version 3 of longhaul got renamed to Powersaver and redesigned
* to use the POWERSAVER MSR at 0x110a.
* It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
* It's pretty much the same feature wise to longhaul v2, though
* there is provision for scaling FSB too, but this doesn't work
* too well in practice so we don't even try to use this.
* *
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
*/ */
...@@ -95,6 +100,27 @@ static int longhaul_get_cpu_mult(void) ...@@ -95,6 +100,27 @@ static int longhaul_get_cpu_mult(void)
} }
static void do_powersaver(union msr_longhaul *longhaul,
unsigned int clock_ratio_index, int version)
{
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul->bits.EnableSoftBusRatio = 1;
longhaul->bits.RevisionKey = 0;
local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
local_irq_enable();
__hlt();
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.EnableSoftBusRatio = 0;
longhaul->bits.RevisionKey = version;
local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
local_irq_enable();
}
/** /**
* longhaul_set_cpu_frequency() * longhaul_set_cpu_frequency()
* @clock_ratio_index : bitpattern of the new multiplier. * @clock_ratio_index : bitpattern of the new multiplier.
...@@ -126,61 +152,54 @@ static void longhaul_setstate(unsigned int clock_ratio_index) ...@@ -126,61 +152,54 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10); dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10);
switch (longhaul_version) { switch (longhaul_version) {
/*
* Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
* Software controlled multipliers only.
*
* *NB* Until we get voltage scaling working v1 & v2 are the same code.
* Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
*/
case 1: case 1:
rdmsrl (MSR_VIA_BCR2, bcr2.val); rdmsrl (MSR_VIA_BCR2, bcr2.val);
/* Enable software clock multiplier */ /* Enable software clock multiplier */
bcr2.bits.ESOFTBF = 1; bcr2.bits.ESOFTBF = 1;
bcr2.bits.CLOCKMUL = clock_ratio_index; bcr2.bits.CLOCKMUL = clock_ratio_index;
local_irq_disable();
wrmsrl (MSR_VIA_BCR2, bcr2.val); wrmsrl (MSR_VIA_BCR2, bcr2.val);
local_irq_enable();
__hlt(); __hlt();
/* Disable software clock multiplier */ /* Disable software clock multiplier */
rdmsrl (MSR_VIA_BCR2, bcr2.val); rdmsrl (MSR_VIA_BCR2, bcr2.val);
bcr2.bits.ESOFTBF = 0; bcr2.bits.ESOFTBF = 0;
local_irq_disable();
wrmsrl (MSR_VIA_BCR2, bcr2.val); wrmsrl (MSR_VIA_BCR2, bcr2.val);
local_irq_enable();
break; break;
/* /*
* Powersaver. (Ezra-T [C5M], Nehemiah [C5N]) * Longhaul v3 (aka Powersaver). (Ezra-T [C5M])
* We can scale voltage with this too, but that's currently * We can scale voltage with this too, but that's currently
* disabled until we come up with a decent 'match freq to voltage' * disabled until we come up with a decent 'match freq to voltage'
* algorithm. * algorithm.
* We also need to do the voltage/freq setting in order depending * When we add voltage scaling, we will also need to do the
* on the direction of scaling (like we do in powernow-k7.c) * voltage/freq setting in order depending on the direction
* Ezra-T was alleged to do FSB scaling too, but it never worked in practice. * of scaling (like we do in powernow-k7.c)
*/ */
case 2: case 2:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); do_powersaver(&longhaul, clock_ratio_index, 3);
longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul.bits.EnableSoftBusRatio = 1;
/* We must program the revision key only with values we
* know about, not blindly copy it from 0:3 */
longhaul.bits.RevisionKey = 3; /* SoftVID & SoftBSEL */
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
__hlt();
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
longhaul.bits.EnableSoftBusRatio = 0;
longhaul.bits.RevisionKey = 3;
wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
break; break;
case 3:
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul.bits.EnableSoftBusRatio = 1;
longhaul.bits.RevisionKey = 0x0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); /*
__hlt(); * Powersaver. (Nehemiah [C5N])
* As for Ezra-T, we don't do voltage yet.
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); * This can do FSB scaling too, but it has never been proven
longhaul.bits.EnableSoftBusRatio = 0; * to work in practice.
longhaul.bits.RevisionKey = 0xf; */
wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); case 3:
do_powersaver(&longhaul, clock_ratio_index, 0xf);
break; break;
} }
...@@ -289,7 +308,11 @@ static int __init longhaul_get_ranges(void) ...@@ -289,7 +308,11 @@ static int __init longhaul_get_ranges(void)
minmult=50; minmult=50;
maxmult=longhaul_get_cpu_mult(); maxmult=longhaul_get_cpu_mult();
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; /* Starting with the 1.2GHz parts, theres a 200MHz bus. */
if ((cpu_khz/1000) > 1200)
fsb = 200;
else
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break; break;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static struct cpufreq_driver longrun_driver; static struct cpufreq_driver longrun_driver;
/** /**
* longrun_{low,high}_freq is needed for the conversion of cpufreq kHz * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
* values into per cent values. In TMTA microcode, the following is valid: * values into per cent values. In TMTA microcode, the following is valid:
* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq) * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
*/ */
...@@ -42,18 +42,18 @@ static void __init longrun_get_policy(struct cpufreq_policy *policy) ...@@ -42,18 +42,18 @@ static void __init longrun_get_policy(struct cpufreq_policy *policy)
policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->policy = CPUFREQ_POLICY_PERFORMANCE;
else else
policy->policy = CPUFREQ_POLICY_POWERSAVE; policy->policy = CPUFREQ_POLICY_POWERSAVE;
rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi); rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
msr_lo &= 0x0000007F; msr_lo &= 0x0000007F;
msr_hi &= 0x0000007F; msr_hi &= 0x0000007F;
if ( longrun_high_freq <= longrun_low_freq ) { if ( longrun_high_freq <= longrun_low_freq ) {
/* Assume degenerate Longrun table */ /* Assume degenerate Longrun table */
policy->min = policy->max = longrun_high_freq; policy->min = policy->max = longrun_high_freq;
} else { } else {
policy->min = longrun_low_freq + msr_lo * policy->min = longrun_low_freq + msr_lo *
((longrun_high_freq - longrun_low_freq) / 100); ((longrun_high_freq - longrun_low_freq) / 100);
policy->max = longrun_low_freq + msr_hi * policy->max = longrun_low_freq + msr_hi *
((longrun_high_freq - longrun_low_freq) / 100); ((longrun_high_freq - longrun_low_freq) / 100);
} }
policy->cpu = 0; policy->cpu = 0;
...@@ -79,9 +79,9 @@ static int longrun_set_policy(struct cpufreq_policy *policy) ...@@ -79,9 +79,9 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
/* Assume degenerate Longrun table */ /* Assume degenerate Longrun table */
pctg_lo = pctg_hi = 100; pctg_lo = pctg_hi = 100;
} else { } else {
pctg_lo = (policy->min - longrun_low_freq) / pctg_lo = (policy->min - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100); ((longrun_high_freq - longrun_low_freq) / 100);
pctg_hi = (policy->max - longrun_low_freq) / pctg_hi = (policy->max - longrun_low_freq) /
((longrun_high_freq - longrun_low_freq) / 100); ((longrun_high_freq - longrun_low_freq) / 100);
} }
...@@ -118,7 +118,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy) ...@@ -118,7 +118,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
* longrun_verify_poliy - verifies a new CPUFreq policy * longrun_verify_poliy - verifies a new CPUFreq policy
* @policy: the policy to verify * @policy: the policy to verify
* *
* Validates a new CPUFreq policy. This function has to be called with * Validates a new CPUFreq policy. This function has to be called with
* cpufreq_driver locked. * cpufreq_driver locked.
*/ */
static int longrun_verify_policy(struct cpufreq_policy *policy) static int longrun_verify_policy(struct cpufreq_policy *policy)
...@@ -127,8 +127,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy) ...@@ -127,8 +127,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
return -EINVAL; return -EINVAL;
policy->cpu = 0; policy->cpu = 0;
cpufreq_verify_within_limits(policy, cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq, policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq); policy->cpuinfo.max_freq);
if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
...@@ -160,7 +160,7 @@ static unsigned int longrun_get(unsigned int cpu) ...@@ -160,7 +160,7 @@ static unsigned int longrun_get(unsigned int cpu)
* TMTA rules: * TMTA rules:
* performance_pctg = (target_freq - low_freq)/(high_freq - low_freq) * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
*/ */
static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
unsigned int *high_freq) unsigned int *high_freq)
{ {
u32 msr_lo, msr_hi; u32 msr_lo, msr_hi;
...@@ -174,9 +174,9 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, ...@@ -174,9 +174,9 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
if (cpu_has(c, X86_FEATURE_LRTI)) { if (cpu_has(c, X86_FEATURE_LRTI)) {
/* if the LongRun Table Interface is present, the /* if the LongRun Table Interface is present, the
* detection is a bit easier: * detection is a bit easier:
* For minimum frequency, read out the maximum * For minimum frequency, read out the maximum
* level (msr_hi), write that into "currently * level (msr_hi), write that into "currently
* selected level", and read out the frequency. * selected level", and read out the frequency.
* For maximum frequency, read out level zero. * For maximum frequency, read out level zero.
*/ */
...@@ -223,7 +223,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, ...@@ -223,7 +223,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
cpuid(0x80860007, &eax, &ebx, &ecx, &edx); cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
/* restore values */ /* restore values */
wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi); wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
} }
/* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq) /* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
...@@ -237,7 +237,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, ...@@ -237,7 +237,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
if ((ecx > 95) || (ecx == 0) || (eax < ebx)) if ((ecx > 95) || (ecx == 0) || (eax < ebx))
return -EIO; return -EIO;
edx = (eax - ebx) / (100 - ecx); edx = (eax - ebx) / (100 - ecx);
*low_freq = edx * 1000; /* back to kHz */ *low_freq = edx * 1000; /* back to kHz */
if (*low_freq > *high_freq) if (*low_freq > *high_freq)
...@@ -249,7 +249,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, ...@@ -249,7 +249,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
static int __init longrun_cpu_init(struct cpufreq_policy *policy) static int __init longrun_cpu_init(struct cpufreq_policy *policy)
{ {
int result = 0; int result = 0;
/* capability check */ /* capability check */
if (policy->cpu != 0) if (policy->cpu != 0)
...@@ -265,15 +265,15 @@ static int __init longrun_cpu_init(struct cpufreq_policy *policy) ...@@ -265,15 +265,15 @@ static int __init longrun_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = longrun_high_freq; policy->cpuinfo.max_freq = longrun_high_freq;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
longrun_get_policy(policy); longrun_get_policy(policy);
return 0; return 0;
} }
static struct cpufreq_driver longrun_driver = { static struct cpufreq_driver longrun_driver = {
.flags = CPUFREQ_CONST_LOOPS, .flags = CPUFREQ_CONST_LOOPS,
.verify = longrun_verify_policy, .verify = longrun_verify_policy,
.setpolicy = longrun_set_policy, .setpolicy = longrun_set_policy,
.get = longrun_get, .get = longrun_get,
.init = longrun_cpu_init, .init = longrun_cpu_init,
.name = "longrun", .name = "longrun",
...@@ -290,7 +290,7 @@ static int __init longrun_init(void) ...@@ -290,7 +290,7 @@ static int __init longrun_init(void)
{ {
struct cpuinfo_x86 *c = cpu_data; struct cpuinfo_x86 *c = cpu_data;
if (c->x86_vendor != X86_VENDOR_TRANSMETA || if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
!cpu_has(c, X86_FEATURE_LONGRUN)) !cpu_has(c, X86_FEATURE_LONGRUN))
return -ENODEV; return -ENODEV;
......
...@@ -184,7 +184,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) ...@@ -184,7 +184,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
"The speedstep_centrino module offers voltage scaling" "The speedstep_centrino module offers voltage scaling"
" in addition of frequency scaling. You should use " " in addition of frequency scaling. You should use "
"that instead of p4-clockmod, if possible.\n"); "that instead of p4-clockmod, if possible.\n");
/* on P-4s, the TSC runs with constant frequency independent wether /* on P-4s, the TSC runs with constant frequency independent whether
* throttling is active or not. */ * throttling is active or not. */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
...@@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) ...@@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
return 0; return 0;
} }
/* on P-4s, the TSC runs with constant frequency independent wether /* on P-4s, the TSC runs with constant frequency independent whether
* throttling is active or not. */ * throttling is active or not. */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
* Licensed under the terms of the GNU GPL License version 2. * Licensed under the terms of the GNU GPL License version 2.
* Based upon datasheets & sample CPUs kindly provided by AMD. * Based upon datasheets & sample CPUs kindly provided by AMD.
* *
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
*
* Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt. * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
* - We cli/sti on stepping A0 CPUs around the FID/VID transition. * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
* Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect. * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
...@@ -29,21 +27,13 @@ ...@@ -29,21 +27,13 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K7_ACPI
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/processor.h> #include <acpi/processor.h>
#endif #endif
#include "powernow-k7.h" #include "powernow-k7.h"
#define DEBUG
#ifdef DEBUG
#define dprintk(msg...) printk(msg)
#else
#define dprintk(msg...) do { } while(0)
#endif
#define PFX "powernow: " #define PFX "powernow: "
...@@ -64,7 +54,7 @@ struct pst_s { ...@@ -64,7 +54,7 @@ struct pst_s {
u8 numpstates; u8 numpstates;
}; };
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K7_ACPI
union powernow_acpi_control_t { union powernow_acpi_control_t {
struct { struct {
unsigned long fid:5, unsigned long fid:5,
...@@ -97,6 +87,7 @@ static int fid_codes[32] = { ...@@ -97,6 +87,7 @@ static int fid_codes[32] = {
*/ */
static int acpi_force; static int acpi_force;
static int debug;
static struct cpufreq_frequency_table *powernow_table; static struct cpufreq_frequency_table *powernow_table;
...@@ -109,6 +100,21 @@ static unsigned int fsb; ...@@ -109,6 +100,21 @@ static unsigned int fsb;
static unsigned int latency; static unsigned int latency;
static char have_a0; static char have_a0;
static void dprintk(const char *fmt, ...)
{
char s[256];
va_list args;
if (debug==0)
return;
va_start(args,fmt);
vsprintf(s, fmt, args);
printk(s);
va_end(args);
}
static int check_fsb(unsigned int fsbspeed) static int check_fsb(unsigned int fsbspeed)
{ {
int delta; int delta;
...@@ -190,13 +196,13 @@ static int get_ranges (unsigned char *pst) ...@@ -190,13 +196,13 @@ static int get_ranges (unsigned char *pst)
speed = powernow_table[j].frequency; speed = powernow_table[j].frequency;
if ((fid_codes[fid] % 10)==5) { if ((fid_codes[fid] % 10)==5) {
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (have_a0 == 1) if (have_a0 == 1)
powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID; powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
#endif #endif
} }
dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid, dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz]) ", fid,
fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000); fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
if (speed < minimum_speed) if (speed < minimum_speed)
...@@ -285,7 +291,7 @@ static void change_speed (unsigned int index) ...@@ -285,7 +291,7 @@ static void change_speed (unsigned int index)
change_VID(vid); change_VID(vid);
change_FID(fid); change_FID(fid);
} }
if (have_a0 == 1) if (have_a0 == 1)
local_irq_enable(); local_irq_enable();
...@@ -294,7 +300,7 @@ static void change_speed (unsigned int index) ...@@ -294,7 +300,7 @@ static void change_speed (unsigned int index)
} }
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K7_ACPI
struct acpi_processor_performance *acpi_processor_perf; struct acpi_processor_performance *acpi_processor_perf;
...@@ -377,7 +383,7 @@ static int powernow_acpi_init(void) ...@@ -377,7 +383,7 @@ static int powernow_acpi_init(void)
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
} }
dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid, dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz]) ", fid,
fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000); fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000, dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000,
mobile_vid_table[vid]%1000); mobile_vid_table[vid]%1000);
...@@ -467,9 +473,9 @@ static int powernow_decode_bios (int maxfid, int startvid) ...@@ -467,9 +473,9 @@ static int powernow_decode_bios (int maxfid, int startvid)
(maxfid==pst->maxfid) && (startvid==pst->startvid)) (maxfid==pst->maxfid) && (startvid==pst->startvid))
{ {
dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst); dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);
dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid); dprintk (KERN_INFO PFX " cpuid: 0x%x ", pst->cpuid);
dprintk ("fsb: %d\t", pst->fsbspeed); dprintk ("fsb: %d ", pst->fsbspeed);
dprintk ("maxFID: 0x%x\t", pst->maxfid); dprintk ("maxFID: 0x%x ", pst->maxfid);
dprintk ("startvid: 0x%x\n", pst->startvid); dprintk ("startvid: 0x%x\n", pst->startvid);
ret = get_ranges ((char *) pst + sizeof (struct pst_s)); ret = get_ranges ((char *) pst + sizeof (struct pst_s));
...@@ -591,14 +597,14 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) ...@@ -591,14 +597,14 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
/* A K7 with powernow technology is set to max frequency by BIOS */ /* A K7 with powernow technology is set to max frequency by BIOS */
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
if (!fsb) { if (!fsb) {
printk(KERN_WARNING PFX "can not determine bus frequency\n"); printk(KERN_WARNING PFX "can not determine bus frequency\n");
return -EINVAL; return -EINVAL;
} }
dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
if (dmi_check_system(powernow_dmi_table) || acpi_force) { if (dmi_check_system(powernow_dmi_table) || acpi_force) {
printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
result = powernow_acpi_init(); result = powernow_acpi_init();
} else { } else {
...@@ -648,14 +654,14 @@ static struct freq_attr* powernow_table_attr[] = { ...@@ -648,14 +654,14 @@ static struct freq_attr* powernow_table_attr[] = {
}; };
static struct cpufreq_driver powernow_driver = { static struct cpufreq_driver powernow_driver = {
.verify = powernow_verify, .verify = powernow_verify,
.target = powernow_target, .target = powernow_target,
.get = powernow_get, .get = powernow_get,
.init = powernow_cpu_init, .init = powernow_cpu_init,
.exit = powernow_cpu_exit, .exit = powernow_cpu_exit,
.name = "powernow-k7", .name = "powernow-k7",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.attr = powernow_table_attr, .attr = powernow_table_attr,
}; };
static int __init powernow_init (void) static int __init powernow_init (void)
...@@ -668,7 +674,7 @@ static int __init powernow_init (void) ...@@ -668,7 +674,7 @@ static int __init powernow_init (void)
static void __exit powernow_exit (void) static void __exit powernow_exit (void)
{ {
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (acpi_processor_perf) { if (acpi_processor_perf) {
acpi_processor_unregister_performance(acpi_processor_perf, 0); acpi_processor_unregister_performance(acpi_processor_perf, 0);
kfree(acpi_processor_perf); kfree(acpi_processor_perf);
...@@ -679,8 +685,10 @@ static void __exit powernow_exit (void) ...@@ -679,8 +685,10 @@ static void __exit powernow_exit (void)
kfree(powernow_table); kfree(powernow_table);
} }
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "enable debug output.");
module_param(acpi_force, int, 0444); module_param(acpi_force, int, 0444);
MODULE_PARM_DESC(acpi_force, "Force ACPI to be used"); MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors."); MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/delay.h> #include <asm/delay.h>
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K8_ACPI
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/processor.h> #include <acpi/processor.h>
#endif #endif
...@@ -664,7 +664,7 @@ static int find_psb_table(struct powernow_k8_data *data) ...@@ -664,7 +664,7 @@ static int find_psb_table(struct powernow_k8_data *data)
return -ENODEV; return -ENODEV;
} }
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K8_ACPI
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
{ {
if (!data->acpi_data.state_count) if (!data->acpi_data.state_count)
...@@ -1024,7 +1024,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -1024,7 +1024,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
return -ENODEV; return -ENODEV;
} }
static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol) static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
{ {
struct powernow_k8_data *data = powernow_data[pol->cpu]; struct powernow_k8_data *data = powernow_data[pol->cpu];
...@@ -1076,7 +1076,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = { ...@@ -1076,7 +1076,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
.verify = powernowk8_verify, .verify = powernowk8_verify,
.target = powernowk8_target, .target = powernowk8_target,
.init = powernowk8_cpu_init, .init = powernowk8_cpu_init,
.exit = powernowk8_cpu_exit, .exit = __devexit_p(powernowk8_cpu_exit),
.get = powernowk8_get, .get = powernowk8_get,
.name = "powernow-k8", .name = "powernow-k8",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -29,7 +29,7 @@ struct powernow_k8_data { ...@@ -29,7 +29,7 @@ struct powernow_k8_data {
* frequency is in kHz */ * frequency is in kHz */
struct cpufreq_frequency_table *powernow_table; struct cpufreq_frequency_table *powernow_table;
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) #ifdef CONFIG_X86_POWERNOW_K8_ACPI
/* the acpi table needs to be kept. it's only available if ACPI was /* the acpi table needs to be kept. it's only available if ACPI was
* used to determine valid frequency/vid/fid states */ * used to determine valid frequency/vid/fid states */
struct acpi_processor_performance acpi_data; struct acpi_processor_performance acpi_data;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org> * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
* *
* WARNING WARNING WARNING * WARNING WARNING WARNING
* *
* This driver manipulates the PERF_CTL MSR, which is only somewhat * This driver manipulates the PERF_CTL MSR, which is only somewhat
* documented. While it seems to work on my laptop, it has not been * documented. While it seems to work on my laptop, it has not been
* tested anywhere else, and it may not work for you, do strange * tested anywhere else, and it may not work for you, do strange
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#include <linux/acpi.h>
#include <acpi/processor.h>
#endif
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
...@@ -41,24 +46,24 @@ ...@@ -41,24 +46,24 @@
struct cpu_id struct cpu_id
{ {
__u8 x86; /* CPU family */ __u8 x86; /* CPU family */
__u8 x86_vendor; /* CPU vendor */
__u8 x86_model; /* model */ __u8 x86_model; /* model */
__u8 x86_mask; /* stepping */ __u8 x86_mask; /* stepping */
}; };
static const struct cpu_id cpu_id_banias = { enum {
.x86_vendor = X86_VENDOR_INTEL, CPU_BANIAS,
.x86 = 6, CPU_DOTHAN_A1,
.x86_model = 9, CPU_DOTHAN_A2,
.x86_mask = 5, CPU_DOTHAN_B0,
}; };
static const struct cpu_id cpu_id_dothan_a1 = { static const struct cpu_id cpu_ids[] = {
.x86_vendor = X86_VENDOR_INTEL, [CPU_BANIAS] = { 6, 9, 5 },
.x86 = 6, [CPU_DOTHAN_A1] = { 6, 13, 1 },
.x86_model = 13, [CPU_DOTHAN_A2] = { 6, 13, 2 },
.x86_mask = 1, [CPU_DOTHAN_B0] = { 6, 13, 6 },
}; };
#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
struct cpu_model struct cpu_model
{ {
...@@ -68,10 +73,11 @@ struct cpu_model ...@@ -68,10 +73,11 @@ struct cpu_model
struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
}; };
static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x); static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
/* 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;
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
...@@ -84,7 +90,7 @@ static struct cpu_model *centrino_model; ...@@ -84,7 +90,7 @@ static struct cpu_model *centrino_model;
.index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \
} }
/* /*
* These voltage tables were derived from the Intel Pentium M * These voltage tables were derived from the Intel Pentium M
* datasheet, document 25261202.pdf, Table 5. I have verified they * datasheet, document 25261202.pdf, Table 5. I have verified they
* are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium
...@@ -103,9 +109,9 @@ static struct cpufreq_frequency_table banias_900[] = ...@@ -103,9 +109,9 @@ static struct cpufreq_frequency_table banias_900[] =
/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */ /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
static struct cpufreq_frequency_table banias_1000[] = static struct cpufreq_frequency_table banias_1000[] =
{ {
OP(600, 844), OP(600, 844),
OP(800, 972), OP(800, 972),
OP(900, 988), OP(900, 988),
OP(1000, 1004), OP(1000, 1004),
{ .frequency = CPUFREQ_TABLE_END } { .frequency = CPUFREQ_TABLE_END }
}; };
...@@ -135,7 +141,7 @@ static struct cpufreq_frequency_table banias_1200[] = ...@@ -135,7 +141,7 @@ static struct cpufreq_frequency_table banias_1200[] =
}; };
/* Intel Pentium M processor 1.30GHz (Banias) */ /* Intel Pentium M processor 1.30GHz (Banias) */
static struct cpufreq_frequency_table banias_1300[] = static struct cpufreq_frequency_table banias_1300[] =
{ {
OP( 600, 956), OP( 600, 956),
OP( 800, 1260), OP( 800, 1260),
...@@ -146,7 +152,7 @@ static struct cpufreq_frequency_table banias_1300[] = ...@@ -146,7 +152,7 @@ static struct cpufreq_frequency_table banias_1300[] =
}; };
/* Intel Pentium M processor 1.40GHz (Banias) */ /* Intel Pentium M processor 1.40GHz (Banias) */
static struct cpufreq_frequency_table banias_1400[] = static struct cpufreq_frequency_table banias_1400[] =
{ {
OP( 600, 956), OP( 600, 956),
OP( 800, 1180), OP( 800, 1180),
...@@ -157,7 +163,7 @@ static struct cpufreq_frequency_table banias_1400[] = ...@@ -157,7 +163,7 @@ static struct cpufreq_frequency_table banias_1400[] =
}; };
/* Intel Pentium M processor 1.50GHz (Banias) */ /* Intel Pentium M processor 1.50GHz (Banias) */
static struct cpufreq_frequency_table banias_1500[] = static struct cpufreq_frequency_table banias_1500[] =
{ {
OP( 600, 956), OP( 600, 956),
OP( 800, 1116), OP( 800, 1116),
...@@ -169,7 +175,7 @@ static struct cpufreq_frequency_table banias_1500[] = ...@@ -169,7 +175,7 @@ static struct cpufreq_frequency_table banias_1500[] =
}; };
/* Intel Pentium M processor 1.60GHz (Banias) */ /* Intel Pentium M processor 1.60GHz (Banias) */
static struct cpufreq_frequency_table banias_1600[] = static struct cpufreq_frequency_table banias_1600[] =
{ {
OP( 600, 956), OP( 600, 956),
OP( 800, 1036), OP( 800, 1036),
...@@ -199,13 +205,13 @@ static struct cpufreq_frequency_table banias_1700[] = ...@@ -199,13 +205,13 @@ static struct cpufreq_frequency_table banias_1700[] =
.max_freq = (max)*1000, \ .max_freq = (max)*1000, \
.op_points = banias_##max, \ .op_points = banias_##max, \
} }
#define BANIAS(max) _BANIAS(&cpu_id_banias, max, #max) #define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
/* CPU models, their operating frequency range, and freq/voltage /* CPU models, their operating frequency range, and freq/voltage
operating points */ operating points */
static struct cpu_model models[] = static struct cpu_model models[] =
{ {
_BANIAS(&cpu_id_banias, 900, " 900"), _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),
BANIAS(1000), BANIAS(1000),
BANIAS(1100), BANIAS(1100),
BANIAS(1200), BANIAS(1200),
...@@ -214,6 +220,12 @@ static struct cpu_model models[] = ...@@ -214,6 +220,12 @@ static struct cpu_model models[] =
BANIAS(1500), BANIAS(1500),
BANIAS(1600), BANIAS(1600),
BANIAS(1700), BANIAS(1700),
/* NULL model_name is a wildcard */
{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
{ NULL, } { NULL, }
}; };
#undef _BANIAS #undef _BANIAS
...@@ -224,19 +236,30 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) ...@@ -224,19 +236,30 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
struct cpu_model *model; struct cpu_model *model;
for(model = models; model->model_name != NULL; model++) for(model = models; model->cpu_id != NULL; model++)
if ((strcmp(cpu->x86_model_id, model->model_name) == 0) && if (centrino_verify_cpu_id(cpu, model->cpu_id) &&
(!centrino_verify_cpu_id(cpu, model->cpu_id))) (model->model_name == NULL ||
strcmp(cpu->x86_model_id, model->model_name) == 0))
break; break;
if (model->model_name == NULL) {
if (model->cpu_id == NULL) {
/* No match at all */
printk(KERN_INFO PFX "no support for CPU model \"%s\": " printk(KERN_INFO PFX "no support for CPU model \"%s\": "
"send /proc/cpuinfo to " MAINTAINER "\n", "send /proc/cpuinfo to " MAINTAINER "\n",
cpu->x86_model_id); cpu->x86_model_id);
return -ENOENT; return -ENOENT;
} }
if (model->op_points == NULL) {
/* Matched a non-match */
printk(KERN_INFO PFX "no table support for CPU model \"%s\": \n",
cpu->x86_model_id);
printk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
return -ENOENT;
}
centrino_model = model; centrino_model = model;
printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n", printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n",
model->model_name, model->max_freq); model->model_name, model->max_freq);
...@@ -247,31 +270,54 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) ...@@ -247,31 +270,54 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x) static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
{ {
if ((c->x86 == x->x86) && if ((c->x86 == x->x86) &&
(c->x86_vendor == x->x86_vendor) &&
(c->x86_model == x->x86_model) && (c->x86_model == x->x86_model) &&
(c->x86_mask == x->x86_mask)) (c->x86_mask == x->x86_mask))
return 0; return 1;
return -ENODEV; return 0;
} }
/* Extract clock in kHz from PERF_CTL value */ /* To be called only after centrino_model is initialized */
static unsigned extract_clock(unsigned msr) static unsigned extract_clock(unsigned msr)
{ {
msr = (msr >> 8) & 0xff; int i;
return msr * 100000;
/*
* Extract clock in kHz from PERF_CTL value
* for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure.
*/
if (centrino_cpu) {
msr = (msr >> 8) & 0xff;
return msr * 100000;
}
if ((!centrino_model) || (!centrino_model->op_points))
return 0;
msr &= 0xffff;
for (i=0;centrino_model->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
if (msr == centrino_model->op_points[i].index)
return centrino_model->op_points[i].frequency;
}
return 0;
} }
/* Return the current CPU frequency in kHz */ /* Return the current CPU frequency in kHz */
static unsigned int get_cur_freq(unsigned int cpu) static unsigned int get_cur_freq(unsigned int cpu)
{ {
unsigned l, h; unsigned l, h;
if (cpu) cpumask_t saved_mask;
saved_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu)
return 0; return 0;
rdmsr(MSR_IA32_PERF_STATUS, l, h); rdmsr(MSR_IA32_PERF_STATUS, l, h);
set_cpus_allowed(current, saved_mask);
return extract_clock(l); return extract_clock(l);
} }
...@@ -280,13 +326,8 @@ static unsigned int get_cur_freq(unsigned int cpu) ...@@ -280,13 +326,8 @@ static unsigned int get_cur_freq(unsigned int cpu)
static struct acpi_processor_performance p; static struct acpi_processor_performance p;
#include <linux/acpi.h>
#include <acpi/processor.h>
#define ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP 0x1
/* /*
* centrino_cpu_init_acpi - register with ACPI P-States library * centrino_cpu_init_acpi - register with ACPI P-States library
* *
* Register with the ACPI P-States library (part of drivers/acpi/processor.c) * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
* in order to determine correct frequency and voltage pairings by reading * in order to determine correct frequency and voltage pairings by reading
...@@ -296,7 +337,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) ...@@ -296,7 +337,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
{ {
union acpi_object arg0 = {ACPI_TYPE_BUFFER}; union acpi_object arg0 = {ACPI_TYPE_BUFFER};
u32 arg0_buf[3]; u32 arg0_buf[3];
struct acpi_object_list arg_list = {1, &arg0}; struct acpi_object_list arg_list = {1, &arg0};
unsigned long cur_freq; unsigned long cur_freq;
int result = 0, i; int result = 0, i;
...@@ -305,12 +346,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) ...@@ -305,12 +346,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
arg0.buffer.pointer = (u8 *) arg0_buf; arg0.buffer.pointer = (u8 *) arg0_buf;
arg0_buf[0] = ACPI_PDC_REVISION_ID; arg0_buf[0] = ACPI_PDC_REVISION_ID;
arg0_buf[1] = 1; arg0_buf[1] = 1;
arg0_buf[2] = ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP; arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR;
p.pdc = &arg_list; p.pdc = &arg_list;
/* register with ACPI core */ /* register with ACPI core */
if (acpi_processor_register_performance(&p, 0)) if (acpi_processor_register_performance(&p, policy->cpu))
return -EIO; return -EIO;
/* verify the acpi_data */ /* verify the acpi_data */
...@@ -318,7 +359,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) ...@@ -318,7 +359,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
printk(KERN_DEBUG "No P-States\n"); printk(KERN_DEBUG "No P-States\n");
result = -ENODEV; result = -ENODEV;
goto err_unreg; goto err_unreg;
} }
if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
(p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
...@@ -340,11 +381,10 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) ...@@ -340,11 +381,10 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
goto err_unreg; goto err_unreg;
} }
if (extract_clock(p.states[i].control) != if (p.states[i].core_frequency > p.states[0].core_frequency) {
(p.states[i].core_frequency * 1000)) { printk(KERN_DEBUG "P%u has larger frequency than P0, skipping\n", i);
printk(KERN_DEBUG "Invalid encoded frequency\n"); p.states[i].core_frequency = 0;
result = -EINVAL; continue;
goto err_unreg;
} }
} }
...@@ -357,29 +397,43 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) ...@@ -357,29 +397,43 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
centrino_model->model_name=NULL; centrino_model->model_name=NULL;
centrino_model->max_freq = p.states[0].core_frequency * 1000; centrino_model->max_freq = p.states[0].core_frequency * 1000;
centrino_model->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * centrino_model->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) *
(p.state_count + 1), GFP_KERNEL); (p.state_count + 1), GFP_KERNEL);
if (!centrino_model->op_points) { if (!centrino_model->op_points) {
result = -ENOMEM; result = -ENOMEM;
goto err_kfree; goto err_kfree;
} }
cur_freq = get_cur_freq(0);
for (i=0; i<p.state_count; i++) { for (i=0; i<p.state_count; i++) {
centrino_model->op_points[i].index = p.states[i].control; centrino_model->op_points[i].index = p.states[i].control;
centrino_model->op_points[i].frequency = p.states[i].core_frequency * 1000; centrino_model->op_points[i].frequency = p.states[i].core_frequency * 1000;
}
centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
cur_freq = get_cur_freq(policy->cpu);
for (i=0; i<p.state_count; i++) {
if (extract_clock(centrino_model->op_points[i].index) !=
(centrino_model->op_points[i].frequency)) {
printk(KERN_DEBUG "Invalid encoded frequency\n");
result = -EINVAL;
goto err_kfree_all;
}
if (cur_freq == centrino_model->op_points[i].frequency) if (cur_freq == centrino_model->op_points[i].frequency)
p.state = i; p.state = i;
if (!p.states[i].core_frequency)
centrino_model->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
} }
centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
return 0; return 0;
err_kfree_all:
kfree(centrino_model->op_points);
err_kfree: err_kfree:
kfree(centrino_model); kfree(centrino_model);
err_unreg: err_unreg:
acpi_processor_unregister_performance(&p, 0); acpi_processor_unregister_performance(&p, policy->cpu);
return (result); return (result);
} }
#else #else
...@@ -392,21 +446,30 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -392,21 +446,30 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
unsigned freq; unsigned freq;
unsigned l, h; unsigned l, h;
int ret; int ret;
int i;
if (policy->cpu != 0) /* Only Intel makes Enhanced Speedstep-capable CPUs */
if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV; return -ENODEV;
if (!cpu_has(cpu, X86_FEATURE_EST)) for (i = 0; i < N_IDS; i++)
return -ENODEV; if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
break;
if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) && if (i != N_IDS)
(centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) { centrino_cpu = 1;
printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
"send /proc/cpuinfo to " MAINTAINER "\n");
return -ENODEV;
}
if (centrino_cpu_init_acpi(policy)) { if (centrino_cpu_init_acpi(policy)) {
if (policy->cpu != 0)
return -ENODEV;
if (!centrino_cpu) {
printk(KERN_INFO PFX "found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER "\n");
return -ENODEV;
}
if (centrino_cpu_init_table(policy)) { if (centrino_cpu_init_table(policy)) {
return -ENODEV; return -ENODEV;
} }
...@@ -415,11 +478,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -415,11 +478,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
/* Check to see if Enhanced SpeedStep is enabled, and try to /* Check to see if Enhanced SpeedStep is enabled, and try to
enable it if not. */ enable it if not. */
rdmsr(MSR_IA32_MISC_ENABLE, l, h); rdmsr(MSR_IA32_MISC_ENABLE, l, h);
if (!(l & (1<<16))) { if (!(l & (1<<16))) {
l |= (1<<16); l |= (1<<16);
wrmsr(MSR_IA32_MISC_ENABLE, l, h); wrmsr(MSR_IA32_MISC_ENABLE, l, h);
/* check to see if it stuck */ /* check to see if it stuck */
rdmsr(MSR_IA32_MISC_ENABLE, l, h); rdmsr(MSR_IA32_MISC_ENABLE, l, h);
if (!(l & (1<<16))) { if (!(l & (1<<16))) {
...@@ -428,7 +491,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -428,7 +491,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
} }
} }
freq = get_cur_freq(0); freq = get_cur_freq(policy->cpu);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
...@@ -436,7 +499,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -436,7 +499,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n", dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n",
policy->policy, policy->cur); policy->policy, policy->cur);
ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points); ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points);
if (ret) if (ret)
return (ret); return (ret);
...@@ -455,7 +518,7 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) ...@@ -455,7 +518,7 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
if (!centrino_model->model_name) { if (!centrino_model->model_name) {
acpi_processor_unregister_performance(&p, 0); acpi_processor_unregister_performance(&p, policy->cpu);
kfree(centrino_model->op_points); kfree(centrino_model->op_points);
kfree(centrino_model); kfree(centrino_model);
} }
...@@ -493,19 +556,35 @@ static int centrino_target (struct cpufreq_policy *policy, ...@@ -493,19 +556,35 @@ static int centrino_target (struct cpufreq_policy *policy,
unsigned int newstate = 0; unsigned int newstate = 0;
unsigned int msr, oldmsr, h; unsigned int msr, oldmsr, h;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
cpumask_t saved_mask;
int retval;
if (centrino_model == NULL) if (centrino_model == NULL)
return -ENODEV; return -ENODEV;
/*
* Support for SMP systems.
* Make sure we are running on the CPU that wants to change frequency
*/
saved_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(policy->cpu));
if (smp_processor_id() != policy->cpu) {
return(-EAGAIN);
}
if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq, if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq,
relation, &newstate)) relation, &newstate)) {
return -EINVAL; retval = -EINVAL;
goto migrate_end;
}
msr = centrino_model->op_points[newstate].index; msr = centrino_model->op_points[newstate].index;
rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
if (msr == (oldmsr & 0xffff)) if (msr == (oldmsr & 0xffff)) {
return 0; retval = 0;
goto migrate_end;
}
/* Hm, old frequency can either be the last value we put in /* Hm, old frequency can either be the last value we put in
PERF_CTL, or whatever it is now. The trouble is that TM2 PERF_CTL, or whatever it is now. The trouble is that TM2
...@@ -514,31 +593,34 @@ static int centrino_target (struct cpufreq_policy *policy, ...@@ -514,31 +593,34 @@ static int centrino_target (struct cpufreq_policy *policy,
tell us something happened, but it may leave the things on tell us something happened, but it may leave the things on
the notifier chain confused; we therefore stick to using the notifier chain confused; we therefore stick to using
the last programmed speed rather than the current speed for the last programmed speed rather than the current speed for
"old". "old".
TODO: work out how the TCC interrupts work, and try to TODO: work out how the TCC interrupts work, and try to
catch the CPU changing things under us. catch the CPU changing things under us.
*/ */
freqs.cpu = 0; freqs.cpu = policy->cpu;
freqs.old = extract_clock(oldmsr); freqs.old = extract_clock(oldmsr);
freqs.new = extract_clock(msr); freqs.new = extract_clock(msr);
dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n", dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n",
target_freq, freqs.old, freqs.new, msr); target_freq, freqs.old, freqs.new, msr);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/* all but 16 LSB are "reserved", so treat them with /* all but 16 LSB are "reserved", so treat them with
care */ care */
oldmsr &= ~0xffff; oldmsr &= ~0xffff;
msr &= 0xffff; msr &= 0xffff;
oldmsr |= msr; oldmsr |= msr;
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0; retval = 0;
migrate_end:
set_cpus_allowed(current, saved_mask);
return (retval);
} }
static struct freq_attr* centrino_attr[] = { static struct freq_attr* centrino_attr[] = {
...@@ -547,12 +629,12 @@ static struct freq_attr* centrino_attr[] = { ...@@ -547,12 +629,12 @@ static struct freq_attr* centrino_attr[] = {
}; };
static struct cpufreq_driver centrino_driver = { static struct cpufreq_driver centrino_driver = {
.name = "centrino", /* should be speedstep-centrino, .name = "centrino", /* should be speedstep-centrino,
but there's a 16 char limit */ but there's a 16 char limit */
.init = centrino_cpu_init, .init = centrino_cpu_init,
.exit = centrino_cpu_exit, .exit = centrino_cpu_exit,
.verify = centrino_verify, .verify = centrino_verify,
.target = centrino_target, .target = centrino_target,
.get = get_cur_freq, .get = get_cur_freq,
.attr = centrino_attr, .attr = centrino_attr,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* for chipsets ICH2-M and ICH3-M. * for chipsets ICH2-M and ICH3-M.
* *
* Many thanks to Ducrot Bruno for finding and fixing the last * Many thanks to Ducrot Bruno for finding and fixing the last
* "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler
* for extensive testing. * for extensive testing.
* *
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*********************************************************************/ *********************************************************************/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -29,24 +29,24 @@ ...@@ -29,24 +29,24 @@
/* speedstep_chipset: /* speedstep_chipset:
* It is necessary to know which chipset is used. As accesses to * It is necessary to know which chipset is used. As accesses to
* this device occur at various places in this module, we need a * this device occur at various places in this module, we need a
* static struct pci_dev * pointing to that device. * static struct pci_dev * pointing to that device.
*/ */
static struct pci_dev *speedstep_chipset_dev; static struct pci_dev *speedstep_chipset_dev;
/* speedstep_processor /* speedstep_processor
*/ */
static unsigned int speedstep_processor = 0; static unsigned int speedstep_processor = 0;
/* /*
* There are only two frequency states for each processor. Values * There are only two frequency states for each processor. Values
* are in kHz for the time being. * are in kHz for the time being.
*/ */
static struct cpufreq_frequency_table speedstep_freqs[] = { static struct cpufreq_frequency_table speedstep_freqs[] = {
{SPEEDSTEP_HIGH, 0}, {SPEEDSTEP_HIGH, 0},
{SPEEDSTEP_LOW, 0}, {SPEEDSTEP_LOW, 0},
{0, CPUFREQ_TABLE_END}, {0, CPUFREQ_TABLE_END},
}; };
...@@ -68,22 +68,21 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { ...@@ -68,22 +68,21 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
* speedstep_set_state - set the SpeedStep state * speedstep_set_state - set the SpeedStep state
* @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
* *
* Tries to change the SpeedStep state. * Tries to change the SpeedStep state.
*/ */
static void speedstep_set_state (unsigned int state) static void speedstep_set_state (unsigned int state)
{ {
u32 pmbase; u32 pmbase;
u8 pm2_blk; u8 pm2_blk;
u8 value; u8 value;
unsigned long flags; unsigned long flags;
if (!speedstep_chipset_dev || (state > 0x1)) if (!speedstep_chipset_dev || (state > 0x1))
return; return;
/* get PMBASE */ /* get PMBASE */
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
if (!(pmbase & 0x01)) if (!(pmbase & 0x01)) {
{
printk(KERN_ERR "cpufreq: could not find speedstep register\n"); printk(KERN_ERR "cpufreq: could not find speedstep register\n");
return; return;
} }
...@@ -146,18 +145,16 @@ static void speedstep_set_state (unsigned int state) ...@@ -146,18 +145,16 @@ static void speedstep_set_state (unsigned int state)
*/ */
static int speedstep_activate (void) static int speedstep_activate (void)
{ {
u16 value = 0; u16 value = 0;
if (!speedstep_chipset_dev) if (!speedstep_chipset_dev)
return -EINVAL; return -EINVAL;
pci_read_config_word(speedstep_chipset_dev, pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value);
0x00A0, &value);
if (!(value & 0x08)) { if (!(value & 0x08)) {
value |= 0x08; value |= 0x08;
dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");
pci_write_config_word(speedstep_chipset_dev, pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
0x00A0, value);
} }
return 0; return 0;
...@@ -167,15 +164,15 @@ static int speedstep_activate (void) ...@@ -167,15 +164,15 @@ static int speedstep_activate (void)
/** /**
* speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic
* *
* Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to
* the LPC bridge / PM module which contains all power-management * the LPC bridge / PM module which contains all power-management
* functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
* chipset, or zero on failure. * chipset, or zero on failure.
*/ */
static unsigned int speedstep_detect_chipset (void) static unsigned int speedstep_detect_chipset (void)
{ {
speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801DB_12, PCI_DEVICE_ID_INTEL_82801DB_12,
PCI_ANY_ID, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
NULL); NULL);
...@@ -183,7 +180,7 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -183,7 +180,7 @@ static unsigned int speedstep_detect_chipset (void)
return 4; /* 4-M */ return 4; /* 4-M */
speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801CA_12, PCI_DEVICE_ID_INTEL_82801CA_12,
PCI_ANY_ID, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
NULL); NULL);
...@@ -198,11 +195,11 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -198,11 +195,11 @@ static unsigned int speedstep_detect_chipset (void)
NULL); NULL);
if (speedstep_chipset_dev) { if (speedstep_chipset_dev) {
/* speedstep.c causes lockups on Dell Inspirons 8000 and /* speedstep.c causes lockups on Dell Inspirons 8000 and
* 8100 which use a pretty old revision of the 82815 * 8100 which use a pretty old revision of the 82815
* host brige. Abort on these systems. * host brige. Abort on these systems.
*/ */
static struct pci_dev *hostbridge; static struct pci_dev *hostbridge;
u8 rev = 0; u8 rev = 0;
hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_MC,
...@@ -212,7 +209,7 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -212,7 +209,7 @@ static unsigned int speedstep_detect_chipset (void)
if (!hostbridge) if (!hostbridge)
return 2; /* 2-M */ return 2; /* 2-M */
pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
if (rev < 5) { if (rev < 5) {
dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n");
...@@ -226,6 +223,23 @@ static unsigned int speedstep_detect_chipset (void) ...@@ -226,6 +223,23 @@ static unsigned int speedstep_detect_chipset (void)
return 0; return 0;
} }
static unsigned int speedstep_get(unsigned int cpu)
{
unsigned int speed;
cpumask_t cpus_allowed,affected_cpu_map;
/* only run on CPU to be set, or on its sibling */
cpus_allowed = current->cpus_allowed;
#ifdef CONFIG_SMP
affected_cpu_map = cpu_sibling_map[cpu];
#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);
return speed;
}
/** /**
* speedstep_target - set a new CPUFreq policy * speedstep_target - set a new CPUFreq policy
...@@ -239,7 +253,7 @@ static int speedstep_target (struct cpufreq_policy *policy, ...@@ -239,7 +253,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation) unsigned int relation)
{ {
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, affected_cpu_map;
int i; int i;
...@@ -247,14 +261,14 @@ static int speedstep_target (struct cpufreq_policy *policy, ...@@ -247,14 +261,14 @@ static int speedstep_target (struct cpufreq_policy *policy,
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.new = speedstep_freqs[newstate].frequency;
freqs.cpu = policy->cpu;
/* no transition necessary */ /* no transition necessary */
if (freqs.old == freqs.new) if (freqs.old == freqs.new)
return 0; return 0;
freqs.old = speedstep_get_processor_frequency(speedstep_processor);
freqs.new = speedstep_freqs[newstate].frequency;
freqs.cpu = policy->cpu;
cpus_allowed = current->cpus_allowed; cpus_allowed = current->cpus_allowed;
/* only run on CPU to be set, or on its sibling */ /* only run on CPU to be set, or on its sibling */
...@@ -301,9 +315,9 @@ static int speedstep_verify (struct cpufreq_policy *policy) ...@@ -301,9 +315,9 @@ static int speedstep_verify (struct cpufreq_policy *policy)
static int speedstep_cpu_init(struct cpufreq_policy *policy) 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,affected_cpu_map;
/* capability check */ /* capability check */
...@@ -324,18 +338,16 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -324,18 +338,16 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
&speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_LOW].frequency,
&speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
&speedstep_set_state); &speedstep_set_state);
if (result) { set_cpus_allowed(current, cpus_allowed);
set_cpus_allowed(current, cpus_allowed); if (result)
return result; return result;
}
/* get current speed setting */ /* get current speed setting */
speed = speedstep_get_processor_frequency(speedstep_processor); speed = speedstep_get(policy->cpu);
set_cpus_allowed(current, cpus_allowed);
if (!speed) if (!speed)
return -EIO; return -EIO;
dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
(speed / 1000)); (speed / 1000));
...@@ -360,11 +372,6 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy) ...@@ -360,11 +372,6 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy)
return 0; return 0;
} }
static unsigned int speedstep_get(unsigned int cpu)
{
return speedstep_get_processor_frequency(speedstep_processor);
}
static struct freq_attr* speedstep_attr[] = { static struct freq_attr* speedstep_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs, &cpufreq_freq_attr_scaling_available_freqs,
NULL, NULL,
...@@ -372,14 +379,14 @@ static struct freq_attr* speedstep_attr[] = { ...@@ -372,14 +379,14 @@ static struct freq_attr* speedstep_attr[] = {
static struct cpufreq_driver speedstep_driver = { static struct cpufreq_driver speedstep_driver = {
.name = "speedstep-ich", .name = "speedstep-ich",
.verify = speedstep_verify, .verify = speedstep_verify,
.target = speedstep_target, .target = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.exit = speedstep_cpu_exit, .exit = speedstep_cpu_exit,
.get = speedstep_get, .get = speedstep_get,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.attr = speedstep_attr, .attr = speedstep_attr,
}; };
......
...@@ -115,6 +115,11 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) ...@@ -115,6 +115,11 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi) : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi)
: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
); );
/* abort if results are obviously incorrect... */
if ((high_mhz + low_mhz) < 600)
return -EINVAL;
*high = high_mhz * 1000; *high = high_mhz * 1000;
*low = low_mhz * 1000; *low = low_mhz * 1000;
...@@ -180,7 +185,7 @@ static void speedstep_set_state (unsigned int state) ...@@ -180,7 +185,7 @@ static void speedstep_set_state (unsigned int state)
local_irq_restore(flags); local_irq_restore(flags);
if (new_state == state) { if (new_state == state) {
dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (freqs.new / 1000), retry, result); dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
} else { } else {
printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* Fixes * Fixes
* Felix Koop : NR_CPUS used properly * Felix Koop : NR_CPUS used properly
* Jose Renau : Handle single CPU case. * Jose Renau : Handle single CPU case.
* Alan Cox : By repeated request 8) - Total BogoMIP report. * Alan Cox : By repeated request 8) - Total BogoMIPS report.
* Greg Wright : Fix for kernel stacks panic. * Greg Wright : Fix for kernel stacks panic.
* Erich Boleyn : MP v1.4 and additional changes. * Erich Boleyn : MP v1.4 and additional changes.
* Matthias Sattler : Changes for 2.1 kernel map. * Matthias Sattler : Changes for 2.1 kernel map.
......
...@@ -265,7 +265,8 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -265,7 +265,8 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{ {
struct cpufreq_freqs *freq = data; struct cpufreq_freqs *freq = data;
write_seqlock_irq(&xtime_lock); if (val != CPUFREQ_RESUMECHANGE)
write_seqlock_irq(&xtime_lock);
if (!ref_freq) { if (!ref_freq) {
ref_freq = freq->old; ref_freq = freq->old;
loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
...@@ -291,7 +292,9 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -291,7 +292,9 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
} }
#endif #endif
} }
write_sequnlock_irq(&xtime_lock);
if (val != CPUFREQ_RESUMECHANGE)
write_sequnlock_irq(&xtime_lock);
return 0; return 0;
} }
......
...@@ -41,4 +41,9 @@ config X86_POWERNOW_K8 ...@@ -41,4 +41,9 @@ config X86_POWERNOW_K8
If in doubt, say N. If in doubt, say N.
config X86_POWERNOW_K8_ACPI
bool
depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
default y
endmenu endmenu
...@@ -99,6 +99,88 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data) ...@@ -99,6 +99,88 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data)
module_put(cpufreq_driver->owner); module_put(cpufreq_driver->owner);
} }
/*********************************************************************
* EXTERNALLY AFFECTING FREQUENCY CHANGES *
*********************************************************************/
/**
* adjust_jiffies - adjust the system "loops_per_jiffy"
*
* This function alters the system "loops_per_jiffy" for the clock
* speed change. Note that loops_per_jiffy cannot be updated on SMP
* systems as each CPU might be scaled differently. So, use the arch
* per-CPU loops_per_jiffy value wherever possible.
*/
#ifndef CONFIG_SMP
static unsigned long l_p_j_ref;
static unsigned int l_p_j_ref_freq;
static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
if (ci->flags & CPUFREQ_CONST_LOOPS)
return;
if (!l_p_j_ref_freq) {
l_p_j_ref = loops_per_jiffy;
l_p_j_ref_freq = ci->old;
}
if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
(val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
(val == CPUFREQ_RESUMECHANGE))
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
}
#else
static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
#endif
/**
* cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
*
* This function calls the transition notifiers and the "adjust_jiffies" function. It is called
* twice on all CPU frequency changes that have external effects.
*/
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{
BUG_ON(irqs_disabled());
freqs->flags = cpufreq_driver->flags;
down_read(&cpufreq_notifier_rwsem);
switch (state) {
case CPUFREQ_PRECHANGE:
/* detect if the driver reported a value as "old frequency" which
* is not equal to what the cpufreq core thinks is "old frequency".
*/
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
(likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
{
if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
panic("CPU Frequency is out of sync.");
printk(KERN_WARNING "Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
}
}
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
if (likely(cpufreq_cpu_data[freqs->cpu]))
cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
break;
}
up_read(&cpufreq_notifier_rwsem);
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/********************************************************************* /*********************************************************************
* SYSFS INTERFACE * * SYSFS INTERFACE *
*********************************************************************/ *********************************************************************/
...@@ -617,8 +699,8 @@ static int cpufreq_resume(struct sys_device * sysdev) ...@@ -617,8 +699,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC) if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC)
panic("CPU Frequency is out of sync."); panic("CPU Frequency is out of sync.");
printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing" printk(KERN_WARNING "Warning: CPU frequency is %u, "
"core thinks of %u, is %u kHz.\n", cpu_policy->cur, cur_freq); "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur);
freqs.cpu = cpu; freqs.cpu = cpu;
freqs.old = cpu_policy->cur; freqs.old = cpu_policy->cur;
...@@ -626,6 +708,8 @@ static int cpufreq_resume(struct sys_device * sysdev) ...@@ -626,6 +708,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs);
adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
cpu_policy->cur = cur_freq;
} }
} }
...@@ -1005,87 +1089,6 @@ int cpufreq_update_policy(unsigned int cpu) ...@@ -1005,87 +1089,6 @@ int cpufreq_update_policy(unsigned int cpu)
EXPORT_SYMBOL(cpufreq_update_policy); EXPORT_SYMBOL(cpufreq_update_policy);
/*********************************************************************
* EXTERNALLY AFFECTING FREQUENCY CHANGES *
*********************************************************************/
/**
* adjust_jiffies - adjust the system "loops_per_jiffy"
*
* This function alters the system "loops_per_jiffy" for the clock
* speed change. Note that loops_per_jiffy cannot be updated on SMP
* systems as each CPU might be scaled differently. So, use the arch
* per-CPU loops_per_jiffy value wherever possible.
*/
#ifndef CONFIG_SMP
static unsigned long l_p_j_ref;
static unsigned int l_p_j_ref_freq;
static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
if (ci->flags & CPUFREQ_CONST_LOOPS)
return;
if (!l_p_j_ref_freq) {
l_p_j_ref = loops_per_jiffy;
l_p_j_ref_freq = ci->old;
}
if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
(val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
(val == CPUFREQ_RESUMECHANGE))
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
}
#else
static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
#endif
/**
* cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
*
* This function calls the transition notifiers and the "adjust_jiffies" function. It is called
* twice on all CPU frequency changes that have external effects.
*/
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{
BUG_ON(irqs_disabled());
freqs->flags = cpufreq_driver->flags;
down_read(&cpufreq_notifier_rwsem);
switch (state) {
case CPUFREQ_PRECHANGE:
/* detect if the driver reported a value as "old frequency" which
* is not equal to what the cpufreq core thinks is "old frequency".
*/
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
{
if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
panic("CPU Frequency is out of sync.");
printk(KERN_WARNING "Warning: CPU frequency out of sync: "
"cpufreq and timing core thinks of %u, is %u kHz.\n",
cpufreq_cpu_data[freqs->cpu]->cur, freqs->old);
freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
}
}
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
break;
}
up_read(&cpufreq_notifier_rwsem);
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/********************************************************************* /*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER * * REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/ *********************************************************************/
......
...@@ -82,6 +82,13 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -82,6 +82,13 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{ {
struct cpufreq_freqs *freq = data; struct cpufreq_freqs *freq = data;
/* Don't update cur_freq if CPU is managed and we're
* waking up: else we won't remember what frequency
* we need to set the CPU to.
*/
if (cpu_is_managed[freq->cpu] && (val == CPUFREQ_RESUMECHANGE))
return 0;
cpu_cur_freq[freq->cpu] = freq->new; cpu_cur_freq[freq->cpu] = freq->new;
return 0; return 0;
...@@ -147,6 +154,9 @@ EXPORT_SYMBOL_GPL(cpufreq_setmax); ...@@ -147,6 +154,9 @@ EXPORT_SYMBOL_GPL(cpufreq_setmax);
#ifdef CONFIG_CPU_FREQ_24_API #ifdef CONFIG_CPU_FREQ_24_API
#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01
static unsigned int warning_print = 0;
/*********************** cpufreq_sysctl interface ********************/ /*********************** cpufreq_sysctl interface ********************/
static int static int
...@@ -162,6 +172,13 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, ...@@ -162,6 +172,13 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
return 0; return 0;
} }
if (!warning_print) {
warning_print++;
printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01\n");
}
if (write) { if (write) {
unsigned int freq; unsigned int freq;
...@@ -197,6 +214,13 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen, ...@@ -197,6 +214,13 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen,
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return -EINVAL; return -EINVAL;
if (!warning_print) {
warning_print++;
printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01\n");
}
if (oldval && oldlenp) { if (oldval && oldlenp) {
size_t oldlen; size_t oldlen;
...@@ -522,6 +546,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, ...@@ -522,6 +546,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
else if (policy->min > cpu_cur_freq[cpu]) else if (policy->min > cpu_cur_freq[cpu])
__cpufreq_driver_target(&current_policy[cpu], policy->min, __cpufreq_driver_target(&current_policy[cpu], policy->min,
CPUFREQ_RELATION_L); CPUFREQ_RELATION_L);
else
__cpufreq_driver_target(&current_policy[cpu], cpu_cur_freq[cpu],
CPUFREQ_RELATION_L);
memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy)); memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
up(&userspace_sem); up(&userspace_sem);
break; break;
......
...@@ -12,9 +12,12 @@ ...@@ -12,9 +12,12 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
#define CPUFREQ_ALL_CPUS ((NR_CPUS)) #define CPUFREQ_ALL_CPUS ((NR_CPUS))
static unsigned int warning_print = 0;
/** /**
* cpufreq_parse_policy - parse a policy string * cpufreq_parse_policy - parse a policy string
* @input_string: the string to parse. * @input_string: the string to parse.
...@@ -110,6 +113,13 @@ static int cpufreq_proc_read ( ...@@ -110,6 +113,13 @@ static int cpufreq_proc_read (
if (off != 0) if (off != 0)
goto end; goto end;
if (!warning_print) {
warning_print++;
printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01\n");
}
p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
for (i=0;i<NR_CPUS;i++) { for (i=0;i<NR_CPUS;i++) {
if (!cpu_online(i)) if (!cpu_online(i))
...@@ -179,6 +189,13 @@ static int cpufreq_proc_write ( ...@@ -179,6 +189,13 @@ static int cpufreq_proc_write (
if (copy_from_user(proc_string, buffer, count)) if (copy_from_user(proc_string, buffer, count))
return -EFAULT; return -EFAULT;
if (!warning_print) {
warning_print++;
printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01\n");
}
proc_string[count] = '\0'; proc_string[count] = '\0';
......
...@@ -101,6 +101,11 @@ __acpi_release_global_lock (unsigned int *lock) ...@@ -101,6 +101,11 @@ __acpi_release_global_lock (unsigned int *lock)
:"=r"(n_hi), "=r"(n_lo) \ :"=r"(n_hi), "=r"(n_lo) \
:"0"(n_hi), "1"(n_lo)) :"0"(n_hi), "1"(n_lo))
/*
* Refer Intel ACPI _PDC support document for bit definitions
*/
#define ACPI_PDC_EST_CAPABILITY_SMP 0xa
#define ACPI_PDC_EST_CAPABILITY_MSR 0x1
/* /*
* Refer Intel ACPI _PDC support document for bit definitions * Refer Intel ACPI _PDC support document for bit definitions
......
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