diff options
Diffstat (limited to 'arch/x86_64/kernel/time.c')
-rw-r--r-- | arch/x86_64/kernel/time.c | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index f8c47c688443..c0844bffbf84 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
@@ -51,7 +51,7 @@ extern int using_apic_timer; | |||
51 | DEFINE_SPINLOCK(rtc_lock); | 51 | DEFINE_SPINLOCK(rtc_lock); |
52 | DEFINE_SPINLOCK(i8253_lock); | 52 | DEFINE_SPINLOCK(i8253_lock); |
53 | 53 | ||
54 | static int nohpet __initdata = 0; | 54 | int nohpet __initdata = 0; |
55 | static int notsc __initdata = 0; | 55 | static int notsc __initdata = 0; |
56 | 56 | ||
57 | #undef HPET_HACK_ENABLE_DANGEROUS | 57 | #undef HPET_HACK_ENABLE_DANGEROUS |
@@ -345,7 +345,7 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs) | |||
345 | #endif | 345 | #endif |
346 | } | 346 | } |
347 | 347 | ||
348 | static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 348 | void main_timer_handler(struct pt_regs *regs) |
349 | { | 349 | { |
350 | static unsigned long rtc_update = 0; | 350 | static unsigned long rtc_update = 0; |
351 | unsigned long tsc; | 351 | unsigned long tsc; |
@@ -458,12 +458,17 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
458 | } | 458 | } |
459 | 459 | ||
460 | write_sequnlock(&xtime_lock); | 460 | write_sequnlock(&xtime_lock); |
461 | } | ||
461 | 462 | ||
463 | static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
464 | { | ||
465 | if (apic_runs_main_timer > 1) | ||
466 | return IRQ_HANDLED; | ||
467 | main_timer_handler(regs); | ||
462 | #ifdef CONFIG_X86_LOCAL_APIC | 468 | #ifdef CONFIG_X86_LOCAL_APIC |
463 | if (using_apic_timer) | 469 | if (using_apic_timer) |
464 | smp_send_timer_broadcast_ipi(); | 470 | smp_send_timer_broadcast_ipi(); |
465 | #endif | 471 | #endif |
466 | |||
467 | return IRQ_HANDLED; | 472 | return IRQ_HANDLED; |
468 | } | 473 | } |
469 | 474 | ||
@@ -843,17 +848,43 @@ static int hpet_reenable(void) | |||
843 | return hpet_timer_stop_set_go(hpet_tick); | 848 | return hpet_timer_stop_set_go(hpet_tick); |
844 | } | 849 | } |
845 | 850 | ||
846 | void __init pit_init(void) | 851 | #define PIT_MODE 0x43 |
852 | #define PIT_CH0 0x40 | ||
853 | |||
854 | static void __init __pit_init(int val, u8 mode) | ||
847 | { | 855 | { |
848 | unsigned long flags; | 856 | unsigned long flags; |
849 | 857 | ||
850 | spin_lock_irqsave(&i8253_lock, flags); | 858 | spin_lock_irqsave(&i8253_lock, flags); |
851 | outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ | 859 | outb_p(mode, PIT_MODE); |
852 | outb_p(LATCH & 0xff, 0x40); /* LSB */ | 860 | outb_p(val & 0xff, PIT_CH0); /* LSB */ |
853 | outb_p(LATCH >> 8, 0x40); /* MSB */ | 861 | outb_p(val >> 8, PIT_CH0); /* MSB */ |
854 | spin_unlock_irqrestore(&i8253_lock, flags); | 862 | spin_unlock_irqrestore(&i8253_lock, flags); |
855 | } | 863 | } |
856 | 864 | ||
865 | void __init pit_init(void) | ||
866 | { | ||
867 | __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ | ||
868 | } | ||
869 | |||
870 | void __init pit_stop_interrupt(void) | ||
871 | { | ||
872 | __pit_init(0, 0x30); /* mode 0 */ | ||
873 | } | ||
874 | |||
875 | void __init stop_timer_interrupt(void) | ||
876 | { | ||
877 | char *name; | ||
878 | if (vxtime.hpet_address) { | ||
879 | name = "HPET"; | ||
880 | hpet_timer_stop_set_go(0); | ||
881 | } else { | ||
882 | name = "PIT"; | ||
883 | pit_stop_interrupt(); | ||
884 | } | ||
885 | printk(KERN_INFO "timer: %s interrupt stopped.\n", name); | ||
886 | } | ||
887 | |||
857 | int __init time_setup(char *str) | 888 | int __init time_setup(char *str) |
858 | { | 889 | { |
859 | report_lost_ticks = 1; | 890 | report_lost_ticks = 1; |
@@ -932,7 +963,7 @@ void __init time_init(void) | |||
932 | * Make an educated guess if the TSC is trustworthy and synchronized | 963 | * Make an educated guess if the TSC is trustworthy and synchronized |
933 | * over all CPUs. | 964 | * over all CPUs. |
934 | */ | 965 | */ |
935 | __init int unsynchronized_tsc(void) | 966 | __cpuinit int unsynchronized_tsc(void) |
936 | { | 967 | { |
937 | #ifdef CONFIG_SMP | 968 | #ifdef CONFIG_SMP |
938 | if (oem_force_hpet_timer()) | 969 | if (oem_force_hpet_timer()) |
@@ -1016,9 +1047,21 @@ static int timer_resume(struct sys_device *dev) | |||
1016 | write_seqlock_irqsave(&xtime_lock,flags); | 1047 | write_seqlock_irqsave(&xtime_lock,flags); |
1017 | xtime.tv_sec = sec; | 1048 | xtime.tv_sec = sec; |
1018 | xtime.tv_nsec = 0; | 1049 | xtime.tv_nsec = 0; |
1050 | if (vxtime.mode == VXTIME_HPET) { | ||
1051 | if (hpet_use_timer) | ||
1052 | vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; | ||
1053 | else | ||
1054 | vxtime.last = hpet_readl(HPET_COUNTER); | ||
1055 | #ifdef CONFIG_X86_PM_TIMER | ||
1056 | } else if (vxtime.mode == VXTIME_PMTMR) { | ||
1057 | pmtimer_resume(); | ||
1058 | #endif | ||
1059 | } else | ||
1060 | vxtime.last_tsc = get_cycles_sync(); | ||
1019 | write_sequnlock_irqrestore(&xtime_lock,flags); | 1061 | write_sequnlock_irqrestore(&xtime_lock,flags); |
1020 | jiffies += sleep_length; | 1062 | jiffies += sleep_length; |
1021 | wall_jiffies += sleep_length; | 1063 | wall_jiffies += sleep_length; |
1064 | monotonic_base += sleep_length * (NSEC_PER_SEC/HZ); | ||
1022 | touch_softlockup_watchdog(); | 1065 | touch_softlockup_watchdog(); |
1023 | return 0; | 1066 | return 0; |
1024 | } | 1067 | } |