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)
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.max_freq = 160000;
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 =
icst525_khz(&cclk_params, vco); /* current freq */
......
......@@ -578,8 +578,8 @@ acpi_cpufreq_cpu_init (
/* detect transition latency */
policy->cpuinfo.transition_latency = 0;
for (i=0;i<perf->state_count;i++) {
if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency;
if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
}
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000;
......
......@@ -170,6 +170,9 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
* 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.
*/
#define ROUNDING 0xf
static int _guess (int guess, int maxmult)
{
int target;
......@@ -177,16 +180,20 @@ static int _guess (int guess, int maxmult)
target = ((maxmult/10)*guess);
if (maxmult%10 != 0)
target += (guess/2);
target &= ~0xf;
target += ROUNDING/2;
target &= ~ROUNDING;
return target;
}
static int guess_fsb(int maxmult)
{
int speed = (cpu_khz/1000) & ~0xf;
int speed = (cpu_khz/1000);
int i;
int speeds[3] = { 66, 100, 133 };
speed += ROUNDING/2;
speed &= ~ROUNDING;
for (i=0; i<3; i++) {
if (_guess(speeds[i],maxmult) == speed)
return speeds[i];
......
......@@ -48,8 +48,7 @@ enum {
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)
{
......@@ -175,6 +174,54 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
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)
{
......@@ -192,15 +239,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
has_N44_O17_errata[policy->cpu] = 1;
}
/* get frequency */
if (!stock_freq) {
if (cpu_khz)
stock_freq = cpu_khz;
else {
printk(KERN_INFO PFX "unknown core frequency - please use module parameter 'stock_freq'\n");
return -EINVAL;
}
}
/* get max frequency */
stock_freq = cpufreq_p4_get_frequency(c);
if (!stock_freq)
return -EINVAL;
/* table init */
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)
/* cpuinfo and default policy values */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 1000;
policy->cpuinfo.transition_latency = 1000000; /* assumed */
policy->cur = stock_freq;
return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
......@@ -269,8 +311,6 @@ static void __exit cpufreq_p4_exit(void)
}
MODULE_PARM(stock_freq, "i");
MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
MODULE_LICENSE ("GPL");
......
......@@ -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 ("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;
}
p++;
......@@ -386,7 +387,11 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
minimum_speed, maximum_speed);
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;
return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
......
......@@ -687,11 +687,13 @@ find_psb_table(void)
if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */
printk(KERN_ERR BFX
"0 vid exceeded with pstate %d\n", j);
kfree(ppst);
return -ENODEV;
}
if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */
printk(KERN_ERR BFX
"maxvid exceeded with pstate %d\n", j);
kfree(ppst);
return -ENODEV;
}
}
......@@ -706,7 +708,7 @@ find_psb_table(void)
for (j = 0; j < numps; j++)
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");
return 0;
......@@ -935,10 +937,7 @@ powernowk8_verify(struct cpufreq_policy *pol)
return -ENODEV;
}
#warning pol->policy is in undefined state here
res = find_match(&targ, &min, &max,
pol->policy == CPUFREQ_POLICY_POWERSAVE ?
SEARCH_DOWN : SEARCH_UP, 0, 0);
res = find_match(&targ, &min, &max, SEARCH_DOWN, 0, 0);
if (!res) {
pol->min = min * 1000;
pol->max = max * 1000;
......@@ -957,9 +956,10 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
/* Take a crude guess here. */
pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US)
+ (3 * (1 << irt) * 10);
/* Take a crude guess here.
* That guess was in microseconds, so multply with 1000 */
pol->cpuinfo.transition_latency = (((rvo + 8) * vstable * VST_UNITS_20US)
+ (3 * (1 << irt) * 10)) * 1000;
if (query_current_values_with_pending_wait())
return -EIO;
......
......@@ -75,13 +75,13 @@ static struct cpufreq_frequency_table op_900[] =
/* Ultra Low Voltage Intel Pentium M processor 1000MHz */
static struct cpufreq_frequency_table op_1000[] =
{
OP(600, 844),
OP(800, 972),
OP(900, 988),
OP(1000, 1004),
{ .frequency = CPUFREQ_TABLE_END }
};
{
OP(600, 844),
OP(800, 972),
OP(900, 988),
OP(1000, 1004),
{ .frequency = CPUFREQ_TABLE_END }
};
/* Low Voltage Intel Pentium M processor 1.10GHz */
static struct cpufreq_frequency_table op_1100[] =
......@@ -175,7 +175,7 @@ static struct cpufreq_frequency_table op_1700[] =
static const struct cpu_model models[] =
{
_CPU( 900, " 900"),
CPU(1000),
CPU(1000),
CPU(1100),
CPU(1200),
CPU(1300),
......
......@@ -106,14 +106,45 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
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);
dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
msr_lo >>= 24;
return (msr_lo * 100000);
/* 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 "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 @@
#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine 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 */
......
......@@ -19,6 +19,7 @@
#include <linux/cpufreq.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/ist.h>
#include "speedstep-lib.h"
......@@ -51,10 +52,14 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
#define SET_SPEEDSTEP_STATE 2
#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
* Define it if you want verbose debug output, e.g. for bug reporting
*/
#define SPEEDSTEP_DEBUG
//#define SPEEDSTEP_DEBUG
#ifdef SPEEDSTEP_DEBUG
#define dprintk(msg...) printk(msg)
......@@ -85,6 +90,9 @@ static int speedstep_smi_ownership (void)
/**
* 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)
......@@ -93,6 +101,9 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
u32 state=0;
u32 function = GET_SPEEDSTEP_FREQS;
if (!(ist_info.event & 0xFFFF))
return -ENODEV;
command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
__asm__ __volatile__("movl $0, %%edi\n"
......@@ -134,10 +145,11 @@ static int speedstep_get_state (void)
*/
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;
struct cpufreq_freqs freqs;
unsigned int function=SET_SPEEDSTEP_STATE;
unsigned int retry = 0;
if (state > 0x1)
return;
......@@ -157,20 +169,28 @@ static void speedstep_set_state (unsigned int state, unsigned int notify)
local_irq_save(flags);
command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
__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)
);
do {
if (retry) {
dprintk(KERN_INFO "cpufreq: retry %u, previous result %u\n", retry, result);
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 */
local_irq_restore(flags);
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 {
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)
......@@ -225,9 +245,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return -ENODEV;
result = speedstep_smi_ownership();
if (result)
if (result) {
dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n");
return -EINVAL;
}
/* detect low and high frequency */
result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency,
......@@ -286,6 +307,7 @@ static struct cpufreq_driver speedstep_driver = {
.target = speedstep_target,
.init = speedstep_cpu_init,
.resume = speedstep_resume,
.owner = THIS_MODULE,
};
/**
......
......@@ -317,9 +317,17 @@ static void mark_offset_tsc_hpet(void)
}
#endif
#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 long loops_per_jiffy_ref = 0;
static unsigned int variable_tsc = 1;
#ifndef CONFIG_SMP
static unsigned long fast_gettimeoffset_ref = 0;
......@@ -344,12 +352,15 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if ((val == CPUFREQ_PRECHANGE && 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
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);
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
}
......@@ -361,7 +372,19 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
static struct notifier_block time_cpufreq_notifier_block = {
.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)
......@@ -403,10 +426,6 @@ static int __init init_tsc(char* override)
* 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!
*/
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
count2 = LATCH; /* initialize counter for mark_offset_tsc() */
......
......@@ -74,7 +74,7 @@ config CPU_FREQ_24_API
help
This enables the /proc/sys/cpu/ sysctl interface for controlling
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
selected governor for the specified CPU.
......
......@@ -57,7 +57,7 @@ struct cpufreq_governor;
struct cpufreq_cpuinfo {
unsigned int max_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 {
......@@ -231,17 +231,18 @@ int cpufreq_update_policy(unsigned int cpu);
/* the proc_intf.c needs this */
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 *
*********************************************************************/
int cpufreq_gov_userspace_init(void);
#ifdef CONFIG_CPU_FREQ_24_API
int cpufreq_setmax(unsigned int cpu);
int cpufreq_set(unsigned int kHz, unsigned int cpu);
unsigned int cpufreq_get(unsigned int cpu);
#ifdef CONFIG_CPU_FREQ_24_API
/* /proc/sys/cpu */
enum {
......@@ -289,8 +290,6 @@ enum {
#endif /* CONFIG_CPU_FREQ_24_API */
#endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */
/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
......@@ -305,6 +304,7 @@ extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace
#endif
/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
......@@ -318,7 +318,6 @@ struct cpufreq_frequency_table {
* order */
};
#if defined(CONFIG_CPU_FREQ_TABLE) || defined(CONFIG_CPU_FREQ_TABLE_MODULE)
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
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);
#endif /* CONFIG_CPU_FREQ_TABLE */
#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