aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/apic.c78
1 files changed, 27 insertions, 51 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 2383bcf18c5d..5cff7970911e 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -338,6 +338,7 @@ void __init setup_boot_APIC_clock(void)
338 void (*real_handler)(struct clock_event_device *dev); 338 void (*real_handler)(struct clock_event_device *dev);
339 unsigned long deltaj; 339 unsigned long deltaj;
340 long delta, deltapm; 340 long delta, deltapm;
341 int pm_referenced = 0;
341 342
342 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" 343 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
343 "calibrating APIC timer ...\n"); 344 "calibrating APIC timer ...\n");
@@ -357,7 +358,8 @@ void __init setup_boot_APIC_clock(void)
357 /* Let the interrupts run */ 358 /* Let the interrupts run */
358 local_irq_enable(); 359 local_irq_enable();
359 360
360 while(lapic_cal_loops <= LAPIC_CAL_LOOPS); 361 while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
362 cpu_relax();
361 363
362 local_irq_disable(); 364 local_irq_disable();
363 365
@@ -394,6 +396,7 @@ void __init setup_boot_APIC_clock(void)
394 "%lu (%ld)\n", (unsigned long) res, delta); 396 "%lu (%ld)\n", (unsigned long) res, delta);
395 delta = (long) res; 397 delta = (long) res;
396 } 398 }
399 pm_referenced = 1;
397 } 400 }
398 401
399 /* Calculate the scaled math multiplication factor */ 402 /* Calculate the scaled math multiplication factor */
@@ -423,68 +426,41 @@ void __init setup_boot_APIC_clock(void)
423 calibration_result / (1000000 / HZ), 426 calibration_result / (1000000 / HZ),
424 calibration_result % (1000000 / HZ)); 427 calibration_result % (1000000 / HZ));
425 428
426
427 apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
428
429 /*
430 * Setup the apic timer manually
431 */
432 local_apic_timer_verify_ok = 1; 429 local_apic_timer_verify_ok = 1;
433 levt->event_handler = lapic_cal_handler;
434 lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
435 lapic_cal_loops = -1;
436 430
437 /* Let the interrupts run */ 431 /* We trust the pm timer based calibration */
438 local_irq_enable(); 432 if (!pm_referenced) {
433 apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
439 434
440 while(lapic_cal_loops <= LAPIC_CAL_LOOPS); 435 /*
436 * Setup the apic timer manually
437 */
438 levt->event_handler = lapic_cal_handler;
439 lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
440 lapic_cal_loops = -1;
441 441
442 local_irq_disable(); 442 /* Let the interrupts run */
443 local_irq_enable();
443 444
444 /* Stop the lapic timer */ 445 while(lapic_cal_loops <= LAPIC_CAL_LOOPS)
445 lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt); 446 cpu_relax();
446 447
447 local_irq_enable(); 448 local_irq_disable();
448 449
449 /* Jiffies delta */ 450 /* Stop the lapic timer */
450 deltaj = lapic_cal_j2 - lapic_cal_j1; 451 lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
451 apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
452 452
453 /* Check, if the PM timer is available */ 453 local_irq_enable();
454 deltapm = lapic_cal_pm2 - lapic_cal_pm1;
455 apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
456 454
457 local_apic_timer_verify_ok = 0; 455 /* Jiffies delta */
456 deltaj = lapic_cal_j2 - lapic_cal_j1;
457 apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
458 458
459 if (deltapm) {
460 if (deltapm > (pm_100ms - pm_thresh) &&
461 deltapm < (pm_100ms + pm_thresh)) {
462 apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
463 /* Check, if the jiffies result is consistent */
464 if (deltaj < LAPIC_CAL_LOOPS-2 ||
465 deltaj > LAPIC_CAL_LOOPS+2) {
466 /*
467 * Not sure, what we can do about this one.
468 * When high resultion timers are active
469 * and the lapic timer does not stop in C3
470 * we are fine. Otherwise more trouble might
471 * be waiting. -- tglx
472 */
473 printk(KERN_WARNING "Global event device %s "
474 "has wrong frequency "
475 "(%lu ticks instead of %d)\n",
476 global_clock_event->name, deltaj,
477 LAPIC_CAL_LOOPS);
478 }
479 local_apic_timer_verify_ok = 1;
480 }
481 } else {
482 /* Check, if the jiffies result is consistent */ 459 /* Check, if the jiffies result is consistent */
483 if (deltaj >= LAPIC_CAL_LOOPS-2 && 460 if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2)
484 deltaj <= LAPIC_CAL_LOOPS+2) {
485 apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); 461 apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
486 local_apic_timer_verify_ok = 1; 462 else
487 } 463 local_apic_timer_verify_ok = 0;
488 } 464 }
489 465
490 if (!local_apic_timer_verify_ok) { 466 if (!local_apic_timer_verify_ok) {