X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fkernel%2Fcpu%2Fcpufreq%2Fp4-clockmod.c;h=4786fedca6ebfcc94897f6e8d84581f61189c2e4;hb=refs%2Fheads%2Fvserver;hp=fa01a95bbaa3137a3649137de6f1c9b8504ff79d;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index fa01a95bb..4786fedca 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -14,28 +14,29 @@ * The author(s) of this software shall not be held liable for damages * of any nature resulting due to the use of this software. This * software is provided AS-IS with no warranties. - * + * * Date Errata Description * 20020525 N44, O17 12.5% or 25% DC causes lockup * */ -#include #include -#include +#include #include #include #include #include #include +#include /* current / set_cpus_allowed() */ -#include +#include #include #include #include "speedstep-lib.h" #define PFX "p4-clockmod: " +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "p4-clockmod", msg) /* * Duty Cycle (3bits), note DC_DISABLE is not specified in @@ -62,21 +63,21 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) return -EINVAL; rdmsr(MSR_IA32_THERM_STATUS, l, h); -#if 0 + if (l & 0x01) - printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); -#endif + dprintk("CPU#%d currently thermal throttled\n", cpu); + if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT)) newstate = DC_38PT; rdmsr(MSR_IA32_THERM_CONTROL, l, h); if (newstate == DC_DISABLE) { - /* printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); */ + dprintk("CPU#%d disabling modulation\n", cpu); wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { - /* printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", - cpu, ((125 * newstate) / 10)); */ - /* bits 63 - 5 : reserved + dprintk("CPU#%d setting duty cycle to %d%%\n", + cpu, ((125 * newstate) / 10)); + /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle * bit 0 : reserved @@ -110,7 +111,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, { unsigned int newstate = DC_RESV; struct cpufreq_freqs freqs; - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; int i; if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate)) @@ -122,26 +123,18 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, if (freqs.new == freqs.old) return 0; - /* switch to physical CPU where state is to be changed*/ - cpus_allowed = current->cpus_allowed; - - /* only run on CPU to be set, or on its sibling */ -#ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); -#endif - /* notifiers */ - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software - * Developer's Manual, Volume 3 + * Developer's Manual, Volume 3 */ - for_each_cpu_mask(i, affected_cpu_map) { + cpus_allowed = current->cpus_allowed; + + for_each_cpu_mask(i, policy->cpus) { cpumask_t this_cpu = cpumask_of_cpu(i); set_cpus_allowed(current, this_cpu); @@ -152,7 +145,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, set_cpus_allowed(current, cpus_allowed); /* notifiers */ - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -169,33 +162,31 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { - if ((c->x86 == 0x06) && (c->x86_model == 0x09)) { - /* Pentium M (Banias) */ - printk(KERN_WARNING PFX "Warning: Pentium M detected. " - "The speedstep_centrino module offers voltage scaling" - " in addition of frequency scaling. You should use " - "that instead of p4-clockmod, if possible.\n"); - return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); - } - - if ((c->x86 == 0x06) && (c->x86_model == 0x13)) { - /* Pentium M (Dothan) */ - printk(KERN_WARNING PFX "Warning: Pentium M detected. " - "The speedstep_centrino module offers voltage scaling" - " in addition of frequency scaling. You should use " - "that instead of p4-clockmod, if possible.\n"); - /* on P-4s, the TSC runs with constant frequency independent wether - * throttling is active or not. */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; - return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); + if (c->x86 == 0x06) { + if (cpu_has(c, X86_FEATURE_EST)) + printk(KERN_WARNING PFX "Warning: EST-capable CPU detected. " + "The acpi-cpufreq module offers voltage scaling" + " in addition of frequency scaling. You should use " + "that instead of p4-clockmod, if possible.\n"); + switch (c->x86_model) { + case 0x0E: /* Core */ + case 0x0F: /* Core Duo */ + p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE); + case 0x0D: /* Pentium M (Dothan) */ + p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + /* fall through */ + case 0x09: /* Pentium M (Banias) */ + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); + } } if (c->x86 != 0xF) { - printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); + printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); 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. */ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; @@ -211,7 +202,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D); } - + static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) { @@ -219,6 +210,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) int cpuid = 0; unsigned int i; +#ifdef CONFIG_SMP + policy->cpus = cpu_sibling_map[policy->cpu]; +#endif + /* Errata workaround */ cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; switch (cpuid) { @@ -227,8 +222,9 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) case 0x0f11: case 0x0f12: has_N44_O17_errata[policy->cpu] = 1; + dprintk("has errata -- disabling low frequencies\n"); } - + /* get max frequency */ stock_freq = cpufreq_p4_get_frequency(c); if (!stock_freq) @@ -242,7 +238,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) p4clockmod_table[i].frequency = (stock_freq * i)/8; } cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); - + /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 1000000; /* assumed */ @@ -254,20 +250,19 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); + cpufreq_frequency_table_put_attr(policy->cpu); return 0; } static unsigned int cpufreq_p4_get(unsigned int cpu) { - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; u32 l, h; cpus_allowed = current->cpus_allowed; - affected_cpu_map = cpumask_of_cpu(cpu); - set_cpus_allowed(current, affected_cpu_map); - BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map)); + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + BUG_ON(smp_processor_id() != cpu); rdmsr(MSR_IA32_THERM_CONTROL, l, h); @@ -291,7 +286,7 @@ static struct freq_attr* p4clockmod_attr[] = { }; static struct cpufreq_driver p4clockmod_driver = { - .verify = cpufreq_p4_verify, + .verify = cpufreq_p4_verify, .target = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, @@ -303,11 +298,12 @@ static struct cpufreq_driver p4clockmod_driver = { static int __init cpufreq_p4_init(void) -{ +{ struct cpuinfo_x86 *c = cpu_data; + int ret; /* - * THERM_CONTROL is architectural for IA32 now, so + * THERM_CONTROL is architectural for IA32 now, so * we can rely on the capability checks */ if (c->x86_vendor != X86_VENDOR_INTEL) @@ -317,9 +313,11 @@ static int __init cpufreq_p4_init(void) !test_bit(X86_FEATURE_ACC, c->x86_capability)) return -ENODEV; - printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); + ret = cpufreq_register_driver(&p4clockmod_driver); + if (!ret) + printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); - return cpufreq_register_driver(&p4clockmod_driver); + return (ret); } @@ -335,4 +333,3 @@ MODULE_LICENSE ("GPL"); late_initcall(cpufreq_p4_init); module_exit(cpufreq_p4_exit); -