aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/speedstep-lib.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index d368b3f5fce8..7c47005a1805 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor);
320unsigned int speedstep_get_freqs(unsigned int processor, 320unsigned int speedstep_get_freqs(unsigned int processor,
321 unsigned int *low_speed, 321 unsigned int *low_speed,
322 unsigned int *high_speed, 322 unsigned int *high_speed,
323 unsigned int *transition_latency,
323 void (*set_state) (unsigned int state)) 324 void (*set_state) (unsigned int state))
324{ 325{
325 unsigned int prev_speed; 326 unsigned int prev_speed;
326 unsigned int ret = 0; 327 unsigned int ret = 0;
327 unsigned long flags; 328 unsigned long flags;
329 struct timeval tv1, tv2;
328 330
329 if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) 331 if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
330 return -EINVAL; 332 return -EINVAL;
@@ -337,7 +339,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
337 return -EIO; 339 return -EIO;
338 340
339 dprintk("previous speed is %u\n", prev_speed); 341 dprintk("previous speed is %u\n", prev_speed);
340 342
341 local_irq_save(flags); 343 local_irq_save(flags);
342 344
343 /* switch to low state */ 345 /* switch to low state */
@@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor,
350 352
351 dprintk("low speed is %u\n", *low_speed); 353 dprintk("low speed is %u\n", *low_speed);
352 354
355 /* start latency measurement */
356 if (transition_latency)
357 do_gettimeofday(&tv1);
358
353 /* switch to high state */ 359 /* switch to high state */
354 set_state(SPEEDSTEP_HIGH); 360 set_state(SPEEDSTEP_HIGH);
361
362 /* end latency measurement */
363 if (transition_latency)
364 do_gettimeofday(&tv2);
365
355 *high_speed = speedstep_get_processor_frequency(processor); 366 *high_speed = speedstep_get_processor_frequency(processor);
356 if (!*high_speed) { 367 if (!*high_speed) {
357 ret = -EIO; 368 ret = -EIO;
@@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor,
369 if (*high_speed != prev_speed) 380 if (*high_speed != prev_speed)
370 set_state(SPEEDSTEP_LOW); 381 set_state(SPEEDSTEP_LOW);
371 382
383 if (transition_latency) {
384 *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
385 tv2.tv_usec - tv1.tv_usec;
386 dprintk("transition latency is %u uSec\n", *transition_latency);
387
388 /* convert uSec to nSec and add 20% for safety reasons */
389 *transition_latency *= 1200;
390
391 /* check if the latency measurement is too high or too low
392 * and set it to a safe value (500uSec) in that case
393 */
394 if (*transition_latency > 10000000 || *transition_latency < 50000) {
395 printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
396 "range (%u nSec), falling back to a safe one of %u nSec.\n",
397 *transition_latency, 500000);
398 *transition_latency = 500000;
399 }
400 }
401
372 out: 402 out:
373 local_irq_restore(flags); 403 local_irq_restore(flags);
374 return (ret); 404 return (ret);