aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/hpet.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/hpet.c')
-rw-r--r--arch/x86/kernel/hpet.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index cd759ad90690..a00545fe5cdd 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -269,6 +269,8 @@ static void hpet_set_mode(enum clock_event_mode mode,
269 now = hpet_readl(HPET_COUNTER); 269 now = hpet_readl(HPET_COUNTER);
270 cmp = now + (unsigned long) delta; 270 cmp = now + (unsigned long) delta;
271 cfg = hpet_readl(HPET_Tn_CFG(timer)); 271 cfg = hpet_readl(HPET_Tn_CFG(timer));
272 /* Make sure we use edge triggered interrupts */
273 cfg &= ~HPET_TN_LEVEL;
272 cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | 274 cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
273 HPET_TN_SETVAL | HPET_TN_32BIT; 275 HPET_TN_SETVAL | HPET_TN_32BIT;
274 hpet_writel(cfg, HPET_Tn_CFG(timer)); 276 hpet_writel(cfg, HPET_Tn_CFG(timer));
@@ -628,11 +630,12 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
628 630
629 switch (action & 0xf) { 631 switch (action & 0xf) {
630 case CPU_ONLINE: 632 case CPU_ONLINE:
631 INIT_DELAYED_WORK(&work.work, hpet_work); 633 INIT_DELAYED_WORK_ON_STACK(&work.work, hpet_work);
632 init_completion(&work.complete); 634 init_completion(&work.complete);
633 /* FIXME: add schedule_work_on() */ 635 /* FIXME: add schedule_work_on() */
634 schedule_delayed_work_on(cpu, &work.work, 0); 636 schedule_delayed_work_on(cpu, &work.work, 0);
635 wait_for_completion(&work.complete); 637 wait_for_completion(&work.complete);
638 destroy_timer_on_stack(&work.work.timer);
636 break; 639 break;
637 case CPU_DEAD: 640 case CPU_DEAD:
638 if (hdev) { 641 if (hdev) {
@@ -896,7 +899,7 @@ static unsigned long hpet_rtc_flags;
896static int hpet_prev_update_sec; 899static int hpet_prev_update_sec;
897static struct rtc_time hpet_alarm_time; 900static struct rtc_time hpet_alarm_time;
898static unsigned long hpet_pie_count; 901static unsigned long hpet_pie_count;
899static unsigned long hpet_t1_cmp; 902static u32 hpet_t1_cmp;
900static unsigned long hpet_default_delta; 903static unsigned long hpet_default_delta;
901static unsigned long hpet_pie_delta; 904static unsigned long hpet_pie_delta;
902static unsigned long hpet_pie_limit; 905static unsigned long hpet_pie_limit;
@@ -904,6 +907,14 @@ static unsigned long hpet_pie_limit;
904static rtc_irq_handler irq_handler; 907static rtc_irq_handler irq_handler;
905 908
906/* 909/*
910 * Check that the hpet counter c1 is ahead of the c2
911 */
912static inline int hpet_cnt_ahead(u32 c1, u32 c2)
913{
914 return (s32)(c2 - c1) < 0;
915}
916
917/*
907 * Registers a IRQ handler. 918 * Registers a IRQ handler.
908 */ 919 */
909int hpet_register_irq_handler(rtc_irq_handler handler) 920int hpet_register_irq_handler(rtc_irq_handler handler)
@@ -1074,7 +1085,7 @@ static void hpet_rtc_timer_reinit(void)
1074 hpet_t1_cmp += delta; 1085 hpet_t1_cmp += delta;
1075 hpet_writel(hpet_t1_cmp, HPET_T1_CMP); 1086 hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
1076 lost_ints++; 1087 lost_ints++;
1077 } while ((long)(hpet_readl(HPET_COUNTER) - hpet_t1_cmp) > 0); 1088 } while (!hpet_cnt_ahead(hpet_t1_cmp, hpet_readl(HPET_COUNTER)));
1078 1089
1079 if (lost_ints) { 1090 if (lost_ints) {
1080 if (hpet_rtc_flags & RTC_PIE) 1091 if (hpet_rtc_flags & RTC_PIE)