X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fkernel%2Fcpu%2Fcpufreq%2Fspeedstep-smi.c;h=5d176b19acfb7890581f80a7b8227ebd9bcfcf30;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=a84273864ff30d078c44982d4cbcb2ca0602dfe5;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index a84273864..5d176b19a 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -36,6 +36,8 @@ static int smi_port = 0; static int smi_cmd = 0; static unsigned int smi_sig = 0; +/* info about the processor */ +static unsigned int speedstep_processor = 0; /* * There are only two frequency states for each processor. Values @@ -113,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" (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; *low = low_mhz * 1000; @@ -137,37 +144,24 @@ static int speedstep_get_state (void) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) ); - return state; + return (state & 1); } /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * @notify: whether to call cpufreq_notify_transition * */ -static void speedstep_set_state (unsigned int state, unsigned int notify) +static void speedstep_set_state (unsigned int state) { - unsigned int old_state, result = 0, command, new_state; + unsigned int 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; - old_state = speedstep_get_state(); - freqs.old = speedstep_freqs[old_state].frequency; - freqs.new = speedstep_freqs[state].frequency; - freqs.cpu = 0; /* speedstep.c is UP only driver */ - - if (old_state == state) - return; - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - /* Disable IRQs */ local_irq_save(flags); @@ -191,14 +185,11 @@ static void speedstep_set_state (unsigned int state, unsigned int notify) local_irq_restore(flags); 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 { printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return; } @@ -215,11 +206,21 @@ static int speedstep_target (struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { unsigned int newstate = 0; + struct cpufreq_freqs freqs; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; - speedstep_set_state(newstate, 1); + freqs.old = speedstep_freqs[speedstep_get_state()].frequency; + freqs.new = speedstep_freqs[newstate].frequency; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (freqs.old == freqs.new) + return 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + speedstep_set_state(newstate); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } @@ -258,9 +259,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) &speedstep_freqs[SPEEDSTEP_HIGH].frequency); if (result) { /* fall back to speedstep_lib.c dection mechanism: try both states out */ - unsigned int speedstep_processor = speedstep_detect_processor(); - dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n"); + if (!speedstep_processor) + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) return -ENODEV; @@ -298,13 +300,23 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) return 0; } - static int speedstep_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); return 0; } +static unsigned int speedstep_get(unsigned int cpu) +{ + if (cpu) + return -ENODEV; + if (!speedstep_processor) + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) + return 0; + return speedstep_get_processor_frequency(speedstep_processor); +} + static int speedstep_resume(struct cpufreq_policy *policy) { @@ -327,6 +339,7 @@ static struct cpufreq_driver speedstep_driver = { .target = speedstep_target, .init = speedstep_cpu_init, .exit = speedstep_cpu_exit, + .get = speedstep_get, .resume = speedstep_resume, .owner = THIS_MODULE, .attr = speedstep_attr,