Skip to content

Commit 2ded6e6

Browse files
Mark LangsdorfKAGA-KOKO
authored andcommitted
x86, hpet: Immediately disable HPET timer 1 if rtc irq is masked
When HPET is operating in RTC mode, the TN_ENABLE bit on timer1 controls whether the HPET or the RTC delivers interrupts to irq8. When the system goes into suspend, the RTC driver sends a signal to the HPET driver so that the HPET releases control of irq8, allowing the RTC to wake the system from suspend. The switchover is accomplished by a write to the HPET configuration registers which currently only occurs while servicing the HPET interrupt. On some systems, I have seen the system suspend before an HPET interrupt occurs, preventing the write to the HPET configuration register and leaving the HPET in control of the irq8. As the HPET is not active during suspend, it does not generate a wake signal and RTC alarms do not work. This patch forces the HPET driver to immediately transfer control of the irq8 channel to the RTC instead of waiting until the next interrupt event. Signed-off-by: Mark Langsdorf <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Tested-by: Andreas Herrmann <[email protected]> Signed-off-by: Andreas Herrmann <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected]
1 parent 4e2b1c4 commit 2ded6e6

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

arch/x86/kernel/hpet.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,14 @@ int hpet_rtc_timer_init(void)
10491049
}
10501050
EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
10511051

1052+
static void hpet_disable_rtc_channel(void)
1053+
{
1054+
unsigned long cfg;
1055+
cfg = hpet_readl(HPET_T1_CFG);
1056+
cfg &= ~HPET_TN_ENABLE;
1057+
hpet_writel(cfg, HPET_T1_CFG);
1058+
}
1059+
10521060
/*
10531061
* The functions below are called from rtc driver.
10541062
* Return 0 if HPET is not being used.
@@ -1060,6 +1068,9 @@ int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
10601068
return 0;
10611069

10621070
hpet_rtc_flags &= ~bit_mask;
1071+
if (unlikely(!hpet_rtc_flags))
1072+
hpet_disable_rtc_channel();
1073+
10631074
return 1;
10641075
}
10651076
EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit);
@@ -1125,15 +1136,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq);
11251136

11261137
static void hpet_rtc_timer_reinit(void)
11271138
{
1128-
unsigned int cfg, delta;
1139+
unsigned int delta;
11291140
int lost_ints = -1;
11301141

1131-
if (unlikely(!hpet_rtc_flags)) {
1132-
cfg = hpet_readl(HPET_T1_CFG);
1133-
cfg &= ~HPET_TN_ENABLE;
1134-
hpet_writel(cfg, HPET_T1_CFG);
1135-
return;
1136-
}
1142+
if (unlikely(!hpet_rtc_flags))
1143+
hpet_disable_rtc_channel();
11371144

11381145
if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
11391146
delta = hpet_default_delta;

0 commit comments

Comments
 (0)