diff options
-rw-r--r-- | arch/i386/kernel/apic.c | 78 |
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) { |