diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-07-24 00:30:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:34 -0400 |
commit | 7e2a31da854dcf8324012a83a31b40bc11e52589 (patch) | |
tree | fb982e22f3d9ac6ec2fc67a96a297dc743ef67e6 /arch/x86 | |
parent | 449321b39f6c6ebfa15d6da24f134240bd51db29 (diff) |
rtc-cmos: avoid spurious irqs
This fixes kernel http://bugzilla.kernel.org/show_bug.cgi?id=11112 (bogus
RTC update IRQs reported) for rtc-cmos, in two ways:
- When HPET is stealing the IRQs, use the first IRQ to grab
the seconds counter which will be monitored (instead of
using whatever was previously in that memory);
- In sane IRQ handling modes, scrub out old IRQ status before
enabling IRQs.
That latter is done by tightening up IRQ handling for rtc-cmos everywhere,
also ensuring that when HPET is used it's the only thing triggering IRQ
reports to userspace; net object shrink.
Also fix a bogus HPET message related to its RTC emulation.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Report-by: W Unruh <unruh@physics.ubc.ca>
Cc: Andrew Victor <avictor.za@gmail.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/hpet.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 0ea6a19bfdfe..ad2b15a1334d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -468,7 +468,7 @@ void hpet_disable(void) | |||
468 | #define RTC_NUM_INTS 1 | 468 | #define RTC_NUM_INTS 1 |
469 | 469 | ||
470 | static unsigned long hpet_rtc_flags; | 470 | static unsigned long hpet_rtc_flags; |
471 | static unsigned long hpet_prev_update_sec; | 471 | static int hpet_prev_update_sec; |
472 | static struct rtc_time hpet_alarm_time; | 472 | static struct rtc_time hpet_alarm_time; |
473 | static unsigned long hpet_pie_count; | 473 | static unsigned long hpet_pie_count; |
474 | static unsigned long hpet_t1_cmp; | 474 | static unsigned long hpet_t1_cmp; |
@@ -575,6 +575,9 @@ int hpet_set_rtc_irq_bit(unsigned long bit_mask) | |||
575 | 575 | ||
576 | hpet_rtc_flags |= bit_mask; | 576 | hpet_rtc_flags |= bit_mask; |
577 | 577 | ||
578 | if ((bit_mask & RTC_UIE) && !(oldbits & RTC_UIE)) | ||
579 | hpet_prev_update_sec = -1; | ||
580 | |||
578 | if (!oldbits) | 581 | if (!oldbits) |
579 | hpet_rtc_timer_init(); | 582 | hpet_rtc_timer_init(); |
580 | 583 | ||
@@ -652,7 +655,7 @@ static void hpet_rtc_timer_reinit(void) | |||
652 | if (hpet_rtc_flags & RTC_PIE) | 655 | if (hpet_rtc_flags & RTC_PIE) |
653 | hpet_pie_count += lost_ints; | 656 | hpet_pie_count += lost_ints; |
654 | if (printk_ratelimit()) | 657 | if (printk_ratelimit()) |
655 | printk(KERN_WARNING "rtc: lost %d interrupts\n", | 658 | printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n", |
656 | lost_ints); | 659 | lost_ints); |
657 | } | 660 | } |
658 | } | 661 | } |
@@ -670,7 +673,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | |||
670 | 673 | ||
671 | if (hpet_rtc_flags & RTC_UIE && | 674 | if (hpet_rtc_flags & RTC_UIE && |
672 | curr_time.tm_sec != hpet_prev_update_sec) { | 675 | curr_time.tm_sec != hpet_prev_update_sec) { |
673 | rtc_int_flag = RTC_UF; | 676 | if (hpet_prev_update_sec >= 0) |
677 | rtc_int_flag = RTC_UF; | ||
674 | hpet_prev_update_sec = curr_time.tm_sec; | 678 | hpet_prev_update_sec = curr_time.tm_sec; |
675 | } | 679 | } |
676 | 680 | ||