Commit 259cf59f authored by Linus Torvalds's avatar Linus Torvalds

Merge centrino speedstep duplicate patches

parents 48818fe1 b8645a8e
...@@ -172,7 +172,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy) ...@@ -172,7 +172,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.max_freq = 160000; policy->cpuinfo.max_freq = 160000;
policy->cpuinfo.min_freq = 12000; policy->cpuinfo.min_freq = 12000;
policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */ policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
policy->cur = policy->min = policy->max = policy->cur = policy->min = policy->max =
icst525_khz(&cclk_params, vco); /* current freq */ icst525_khz(&cclk_params, vco); /* current freq */
......
...@@ -578,8 +578,8 @@ acpi_cpufreq_cpu_init ( ...@@ -578,8 +578,8 @@ acpi_cpufreq_cpu_init (
/* detect transition latency */ /* detect transition latency */
policy->cpuinfo.transition_latency = 0; policy->cpuinfo.transition_latency = 0;
for (i=0;i<perf->state_count;i++) { for (i=0;i<perf->state_count;i++) {
if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency) if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency; policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
} }
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000; policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000;
......
...@@ -170,6 +170,9 @@ static void longhaul_setstate (unsigned int clock_ratio_index) ...@@ -170,6 +170,9 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
* between that value multiplied by possible FSBs and cpu_mhz which * between that value multiplied by possible FSBs and cpu_mhz which
* was calculated at boot time. Really ugly, but no other way to do this. * was calculated at boot time. Really ugly, but no other way to do this.
*/ */
#define ROUNDING 0xf
static int _guess (int guess, int maxmult) static int _guess (int guess, int maxmult)
{ {
int target; int target;
...@@ -177,16 +180,20 @@ static int _guess (int guess, int maxmult) ...@@ -177,16 +180,20 @@ static int _guess (int guess, int maxmult)
target = ((maxmult/10)*guess); target = ((maxmult/10)*guess);
if (maxmult%10 != 0) if (maxmult%10 != 0)
target += (guess/2); target += (guess/2);
target &= ~0xf; target += ROUNDING/2;
target &= ~ROUNDING;
return target; return target;
} }
static int guess_fsb(int maxmult) static int guess_fsb(int maxmult)
{ {
int speed = (cpu_khz/1000) & ~0xf; int speed = (cpu_khz/1000);
int i; int i;
int speeds[3] = { 66, 100, 133 }; int speeds[3] = { 66, 100, 133 };
speed += ROUNDING/2;
speed &= ~ROUNDING;
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
if (_guess(speeds[i],maxmult) == speed) if (_guess(speeds[i],maxmult) == speed)
return speeds[i]; return speeds[i];
......
...@@ -48,8 +48,7 @@ enum { ...@@ -48,8 +48,7 @@ enum {
static int has_N44_O17_errata[NR_CPUS]; static int has_N44_O17_errata[NR_CPUS];
static int stock_freq; static unsigned int stock_freq;
static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
{ {
...@@ -175,6 +174,54 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) ...@@ -175,6 +174,54 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]); return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
} }
/* copied from speedstep_lib, made SMP-compatible */
static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
{
u32 msr_lo, msr_hi, mult;
unsigned int fsb = 0;
if (c->x86 != 0xF) {
printk(KERN_DEBUG PFX "Unknown P4. Please send an e-mail to <linux@brodo.de>\n");
return 0;
}
rdmsr(0x2c, msr_lo, msr_hi);
/* printk(KERN_DEBUG PFX "P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); */
/* decode the FSB: see IA-32 Intel (C) Architecture Software
* Developer's Manual, Volume 3: System Prgramming Guide,
* revision #12 in Table B-1: MSRs in the Pentium 4 and
* Intel Xeon Processors, on page B-4 and B-5.
*/
if (c->x86_model < 2)
fsb = 100 * 1000;
else {
u8 fsb_code = (msr_lo >> 16) & 0x7;
switch (fsb_code) {
case 0:
fsb = 100 * 1000;
break;
case 1:
fsb = 13333 * 10;
break;
case 2:
fsb = 200 * 1000;
break;
}
}
if (!fsb) {
printk(KERN_DEBUG PFX "couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
printk(KERN_DEBUG PFX "P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
}
/* Multiplier. */
mult = msr_lo >> 24;
return (fsb * mult);
}
static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
{ {
...@@ -192,15 +239,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -192,15 +239,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
has_N44_O17_errata[policy->cpu] = 1; has_N44_O17_errata[policy->cpu] = 1;
} }
/* get frequency */ /* get max frequency */
if (!stock_freq) { stock_freq = cpufreq_p4_get_frequency(c);
if (cpu_khz) if (!stock_freq)
stock_freq = cpu_khz; return -EINVAL;
else {
printk(KERN_INFO PFX "unknown core frequency - please use module parameter 'stock_freq'\n");
return -EINVAL;
}
}
/* table init */ /* table init */
for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) { for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
...@@ -213,7 +255,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -213,7 +255,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */ /* cpuinfo and default policy values */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 1000; policy->cpuinfo.transition_latency = 1000000; /* assumed */
policy->cur = stock_freq; policy->cur = stock_freq;
return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]); return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
...@@ -269,8 +311,6 @@ static void __exit cpufreq_p4_exit(void) ...@@ -269,8 +311,6 @@ static void __exit cpufreq_p4_exit(void)
} }
MODULE_PARM(stock_freq, "i");
MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>"); MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)"); MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
......
...@@ -337,7 +337,8 @@ static int powernow_decode_bios (int maxfid, int startvid) ...@@ -337,7 +337,8 @@ static int powernow_decode_bios (int maxfid, int startvid)
} }
} }
printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple); printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
printk ("This is indicative of a broken BIOS. Email davej@redhat.com\n"); printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");
printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n");
return -EINVAL; return -EINVAL;
} }
p++; p++;
...@@ -386,7 +387,11 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) ...@@ -386,7 +387,11 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
minimum_speed, maximum_speed); minimum_speed, maximum_speed);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = latency;
/* latency is in 10 ns (look for SGTC above) for each VID
* and FID transition, so multiply that value with 20 */
policy->cpuinfo.transition_latency = latency * 20;
policy->cur = maximum_speed; policy->cur = maximum_speed;
return cpufreq_frequency_table_cpuinfo(policy, powernow_table); return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
......
...@@ -687,11 +687,13 @@ find_psb_table(void) ...@@ -687,11 +687,13 @@ find_psb_table(void)
if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */ if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */
printk(KERN_ERR BFX printk(KERN_ERR BFX
"0 vid exceeded with pstate %d\n", j); "0 vid exceeded with pstate %d\n", j);
kfree(ppst);
return -ENODEV; return -ENODEV;
} }
if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */ if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */
printk(KERN_ERR BFX printk(KERN_ERR BFX
"maxvid exceeded with pstate %d\n", j); "maxvid exceeded with pstate %d\n", j);
kfree(ppst);
return -ENODEV; return -ENODEV;
} }
} }
...@@ -706,7 +708,7 @@ find_psb_table(void) ...@@ -706,7 +708,7 @@ find_psb_table(void)
for (j = 0; j < numps; j++) for (j = 0; j < numps; j++)
if ((ppst[j].fid==currfid) && (ppst[j].vid==currvid)) if ((ppst[j].fid==currfid) && (ppst[j].vid==currvid))
return (0); return 0;
printk(KERN_ERR BFX "currfid/vid do not match PST, ignoring\n"); printk(KERN_ERR BFX "currfid/vid do not match PST, ignoring\n");
return 0; return 0;
...@@ -935,10 +937,7 @@ powernowk8_verify(struct cpufreq_policy *pol) ...@@ -935,10 +937,7 @@ powernowk8_verify(struct cpufreq_policy *pol)
return -ENODEV; return -ENODEV;
} }
#warning pol->policy is in undefined state here res = find_match(&targ, &min, &max, SEARCH_DOWN, 0, 0);
res = find_match(&targ, &min, &max,
pol->policy == CPUFREQ_POLICY_POWERSAVE ?
SEARCH_DOWN : SEARCH_UP, 0, 0);
if (!res) { if (!res) {
pol->min = min * 1000; pol->min = min * 1000;
pol->max = max * 1000; pol->max = max * 1000;
...@@ -957,9 +956,10 @@ powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -957,9 +956,10 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
pol->governor = CPUFREQ_DEFAULT_GOVERNOR; pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
/* Take a crude guess here. */ /* Take a crude guess here.
pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US) * That guess was in microseconds, so multply with 1000 */
+ (3 * (1 << irt) * 10); pol->cpuinfo.transition_latency = (((rvo + 8) * vstable * VST_UNITS_20US)
+ (3 * (1 << irt) * 10)) * 1000;
if (query_current_values_with_pending_wait()) if (query_current_values_with_pending_wait())
return -EIO; return -EIO;
......
...@@ -75,13 +75,13 @@ static struct cpufreq_frequency_table op_900[] = ...@@ -75,13 +75,13 @@ static struct cpufreq_frequency_table op_900[] =
/* Ultra Low Voltage Intel Pentium M processor 1000MHz */ /* Ultra Low Voltage Intel Pentium M processor 1000MHz */
static struct cpufreq_frequency_table op_1000[] = static struct cpufreq_frequency_table op_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 }
}; };
/* Low Voltage Intel Pentium M processor 1.10GHz */ /* Low Voltage Intel Pentium M processor 1.10GHz */
static struct cpufreq_frequency_table op_1100[] = static struct cpufreq_frequency_table op_1100[] =
...@@ -175,7 +175,7 @@ static struct cpufreq_frequency_table op_1700[] = ...@@ -175,7 +175,7 @@ static struct cpufreq_frequency_table op_1700[] =
static const struct cpu_model models[] = static const struct cpu_model models[] =
{ {
_CPU( 900, " 900"), _CPU( 900, " 900"),
CPU(1000), CPU(1000),
CPU(1100), CPU(1100),
CPU(1200), CPU(1200),
CPU(1300), CPU(1300),
......
...@@ -106,14 +106,45 @@ static unsigned int pentium3_get_frequency (unsigned int processor) ...@@ -106,14 +106,45 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
static unsigned int pentium4_get_frequency(void) static unsigned int pentium4_get_frequency(void)
{ {
u32 msr_lo, msr_hi; struct cpuinfo_x86 *c = &boot_cpu_data;
u32 msr_lo, msr_hi, mult;
unsigned int fsb = 0;
rdmsr(0x2c, msr_lo, msr_hi); rdmsr(0x2c, msr_lo, msr_hi);
dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
msr_lo >>= 24; /* decode the FSB: see IA-32 Intel (C) Architecture Software
return (msr_lo * 100000); * Developer's Manual, Volume 3: System Prgramming Guide,
* revision #12 in Table B-1: MSRs in the Pentium 4 and
* Intel Xeon Processors, on page B-4 and B-5.
*/
if (c->x86_model < 2)
fsb = 100 * 1000;
else {
u8 fsb_code = (msr_lo >> 16) & 0x7;
switch (fsb_code) {
case 0:
fsb = 100 * 1000;
break;
case 1:
fsb = 13333 * 10;
break;
case 2:
fsb = 200 * 1000;
break;
}
}
if (!fsb)
printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
/* Multiplier. */
mult = msr_lo >> 24;
dprintk(KERN_DEBUG "speedstep-lib: P4 - FSB %u kHz; Multiplier %u\n", fsb, mult);
return (fsb * mult);
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */ #define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */ #define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ #define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */
#define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M with 100 MHz FSB */ #define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M */
/* speedstep states -- only two of them */ /* speedstep states -- only two of them */
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <asm/ist.h> #include <asm/ist.h>
#include "speedstep-lib.h" #include "speedstep-lib.h"
...@@ -51,10 +52,14 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { ...@@ -51,10 +52,14 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
#define SET_SPEEDSTEP_STATE 2 #define SET_SPEEDSTEP_STATE 2
#define GET_SPEEDSTEP_FREQS 4 #define GET_SPEEDSTEP_FREQS 4
/* how often shall the SMI call be tried if it failed, e.g. because
* of DMA activity going on? */
#define SMI_TRIES 5
/* DEBUG /* DEBUG
* Define it if you want verbose debug output, e.g. for bug reporting * Define it if you want verbose debug output, e.g. for bug reporting
*/ */
#define SPEEDSTEP_DEBUG //#define SPEEDSTEP_DEBUG
#ifdef SPEEDSTEP_DEBUG #ifdef SPEEDSTEP_DEBUG
#define dprintk(msg...) printk(msg) #define dprintk(msg...) printk(msg)
...@@ -85,6 +90,9 @@ static int speedstep_smi_ownership (void) ...@@ -85,6 +90,9 @@ static int speedstep_smi_ownership (void)
/** /**
* speedstep_smi_get_freqs - get SpeedStep preferred & current freq. * speedstep_smi_get_freqs - get SpeedStep preferred & current freq.
* Only available on later SpeedStep-enabled systems, returns false results or
* even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing
* shows that the latter occurs if !(ist_info.event & 0xFFFF).
* *
*/ */
static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
...@@ -93,6 +101,9 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) ...@@ -93,6 +101,9 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
u32 state=0; u32 state=0;
u32 function = GET_SPEEDSTEP_FREQS; u32 function = GET_SPEEDSTEP_FREQS;
if (!(ist_info.event & 0xFFFF))
return -ENODEV;
command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
__asm__ __volatile__("movl $0, %%edi\n" __asm__ __volatile__("movl $0, %%edi\n"
...@@ -134,10 +145,11 @@ static int speedstep_get_state (void) ...@@ -134,10 +145,11 @@ static int speedstep_get_state (void)
*/ */
static void speedstep_set_state (unsigned int state, unsigned int notify) static void speedstep_set_state (unsigned int state, unsigned int notify)
{ {
unsigned int old_state, result, command, new_state; unsigned int old_state, result = 0, command, new_state;
unsigned long flags; unsigned long flags;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
unsigned int function=SET_SPEEDSTEP_STATE; unsigned int function=SET_SPEEDSTEP_STATE;
unsigned int retry = 0;
if (state > 0x1) if (state > 0x1)
return; return;
...@@ -157,20 +169,28 @@ static void speedstep_set_state (unsigned int state, unsigned int notify) ...@@ -157,20 +169,28 @@ static void speedstep_set_state (unsigned int state, unsigned int notify)
local_irq_save(flags); local_irq_save(flags);
command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
__asm__ __volatile__(
"movl $0, %%edi\n" do {
"out %%al, (%%dx)\n" if (retry) {
: "=b" (new_state), "=D" (result) dprintk(KERN_INFO "cpufreq: retry %u, previous result %u\n", retry, result);
: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) mdelay(retry * 50);
); }
retry++;
__asm__ __volatile__(
"movl $0, %%edi\n"
"out %%al, (%%dx)\n"
: "=b" (new_state), "=D" (result)
: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
);
} while ((new_state != state) && (retry <= SMI_TRIES));
/* enable IRQs */ /* enable IRQs */
local_irq_restore(flags); local_irq_restore(flags);
if (new_state == state) { if (new_state == state) {
dprintk(KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (freqs.new / 1000), retry, result);
} else { } else {
printk(KERN_ERR "cpufreq: change failed\n"); printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
} }
if (notify) if (notify)
...@@ -225,9 +245,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -225,9 +245,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return -ENODEV; return -ENODEV;
result = speedstep_smi_ownership(); result = speedstep_smi_ownership();
if (result) {
if (result)
dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n"); dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n");
return -EINVAL;
}
/* detect low and high frequency */ /* detect low and high frequency */
result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency, result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency,
...@@ -286,6 +307,7 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -286,6 +307,7 @@ static struct cpufreq_driver speedstep_driver = {
.target = speedstep_target, .target = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.resume = speedstep_resume, .resume = speedstep_resume,
.owner = THIS_MODULE,
}; };
/** /**
......
...@@ -317,9 +317,17 @@ static void mark_offset_tsc_hpet(void) ...@@ -317,9 +317,17 @@ static void mark_offset_tsc_hpet(void)
} }
#endif #endif
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
/* If the CPU frequency is scaled, TSC-based delays will need a different
* loops_per_jiffy value to function properly. An exception to this
* are modern Intel Pentium 4 processors, where the TSC runs at a constant
* speed independent of frequency scaling.
*/
static unsigned int ref_freq = 0; static unsigned int ref_freq = 0;
static unsigned long loops_per_jiffy_ref = 0; static unsigned long loops_per_jiffy_ref = 0;
static unsigned int variable_tsc = 1;
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
static unsigned long fast_gettimeoffset_ref = 0; static unsigned long fast_gettimeoffset_ref = 0;
...@@ -344,12 +352,15 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -344,12 +352,15 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); if (variable_tsc)
cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
if (use_tsc) { if (use_tsc) {
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
set_cyc2ns_scale(cpu_khz/1000); if (variable_tsc) {
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
set_cyc2ns_scale(cpu_khz/1000);
}
} }
#endif #endif
} }
...@@ -361,7 +372,19 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -361,7 +372,19 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
static struct notifier_block time_cpufreq_notifier_block = { static struct notifier_block time_cpufreq_notifier_block = {
.notifier_call = time_cpufreq_notifier .notifier_call = time_cpufreq_notifier
}; };
#endif
static int __init cpufreq_tsc(void)
{
/* P4 and above CPU TSC freq doesn't change when CPU frequency changes*/
if ((boot_cpu_data.x86 >= 15) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
variable_tsc = 0;
return cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
}
core_initcall(cpufreq_tsc);
#endif
static int __init init_tsc(char* override) static int __init init_tsc(char* override)
...@@ -403,10 +426,6 @@ static int __init init_tsc(char* override) ...@@ -403,10 +426,6 @@ static int __init init_tsc(char* override)
* some CPU's have a TSC. Thats never worked and nobody has * some CPU's have a TSC. Thats never worked and nobody has
* moaned if you have the only one in the world - you fix it! * moaned if you have the only one in the world - you fix it!
*/ */
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
count2 = LATCH; /* initialize counter for mark_offset_tsc() */ count2 = LATCH; /* initialize counter for mark_offset_tsc() */
......
...@@ -74,7 +74,7 @@ config CPU_FREQ_24_API ...@@ -74,7 +74,7 @@ config CPU_FREQ_24_API
help help
This enables the /proc/sys/cpu/ sysctl interface for controlling This enables the /proc/sys/cpu/ sysctl interface for controlling
the CPUFreq,"userspace" governor. This is the same interface the CPUFreq,"userspace" governor. This is the same interface
as known from the.4.-kernel patches for CPUFreq, and offers as known from the 2.4.-kernel patches for CPUFreq, and offers
the same functionality as long as "userspace" is the the same functionality as long as "userspace" is the
selected governor for the specified CPU. selected governor for the specified CPU.
......
...@@ -57,7 +57,7 @@ struct cpufreq_governor; ...@@ -57,7 +57,7 @@ struct cpufreq_governor;
struct cpufreq_cpuinfo { struct cpufreq_cpuinfo {
unsigned int max_freq; unsigned int max_freq;
unsigned int min_freq; unsigned int min_freq;
unsigned int transition_latency; /* in 10^(-9) s */ unsigned int transition_latency; /* in 10^(-9) s = nanoseconds */
}; };
struct cpufreq_real_policy { struct cpufreq_real_policy {
...@@ -231,17 +231,18 @@ int cpufreq_update_policy(unsigned int cpu); ...@@ -231,17 +231,18 @@ int cpufreq_update_policy(unsigned int cpu);
/* the proc_intf.c needs this */ /* the proc_intf.c needs this */
int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor); int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor);
#if defined(CONFIG_CPU_FREQ_GOV_USERSPACE) || defined(CONFIG_CPU_FREQ_GOV_USERSPACE_MODULE)
/********************************************************************* /*********************************************************************
* CPUFREQ USERSPACE GOVERNOR * * CPUFREQ USERSPACE GOVERNOR *
*********************************************************************/ *********************************************************************/
int cpufreq_gov_userspace_init(void); int cpufreq_gov_userspace_init(void);
#ifdef CONFIG_CPU_FREQ_24_API
int cpufreq_setmax(unsigned int cpu); int cpufreq_setmax(unsigned int cpu);
int cpufreq_set(unsigned int kHz, unsigned int cpu); int cpufreq_set(unsigned int kHz, unsigned int cpu);
unsigned int cpufreq_get(unsigned int cpu); unsigned int cpufreq_get(unsigned int cpu);
#ifdef CONFIG_CPU_FREQ_24_API
/* /proc/sys/cpu */ /* /proc/sys/cpu */
enum { enum {
...@@ -289,8 +290,6 @@ enum { ...@@ -289,8 +290,6 @@ enum {
#endif /* CONFIG_CPU_FREQ_24_API */ #endif /* CONFIG_CPU_FREQ_24_API */
#endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */
/********************************************************************* /*********************************************************************
* CPUFREQ DEFAULT GOVERNOR * * CPUFREQ DEFAULT GOVERNOR *
...@@ -305,6 +304,7 @@ extern struct cpufreq_governor cpufreq_gov_userspace; ...@@ -305,6 +304,7 @@ extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace
#endif #endif
/********************************************************************* /*********************************************************************
* FREQUENCY TABLE HELPERS * * FREQUENCY TABLE HELPERS *
*********************************************************************/ *********************************************************************/
...@@ -318,7 +318,6 @@ struct cpufreq_frequency_table { ...@@ -318,7 +318,6 @@ struct cpufreq_frequency_table {
* order */ * order */
}; };
#if defined(CONFIG_CPU_FREQ_TABLE) || defined(CONFIG_CPU_FREQ_TABLE_MODULE)
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table); struct cpufreq_frequency_table *table);
...@@ -340,5 +339,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, ...@@ -340,5 +339,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
void cpufreq_frequency_table_put_attr(unsigned int cpu); void cpufreq_frequency_table_put_attr(unsigned int cpu);
#endif /* CONFIG_CPU_FREQ_TABLE */
#endif /* _LINUX_CPUFREQ_H */ #endif /* _LINUX_CPUFREQ_H */
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