Home Home > GIT Browse
diff options
authorIngo Molnar <mingo@elte.hu>2008-08-23 17:59:07 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-08 19:44:41 -0700
commit80ad012478ee989402ac014aab956e4534acd498 (patch)
parentf54fd05032fea1808f5e76dc8a94cde40f5d9f01 (diff)
rtc: fix deadlock
commit 38c052f8cff1bd323ccfa968136a9556652ee420 upstream if get_rtc_time() is _ever_ called with IRQs off, we deadlock badly in it, waiting for jiffies to increment. So make the code more robust by doing an explicit mdelay(20). This solves a very hard to reproduce/debug hard lockup reported by Mikael Pettersson. Reported-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1 files changed, 4 insertions, 8 deletions
diff --git a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
index dd1bed860e64..85286fb36237 100644
--- a/include/asm-generic/rtc.h
+++ b/include/asm-generic/rtc.h
@@ -17,6 +17,7 @@
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/delay.h>
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
@@ -45,7 +46,6 @@ static inline unsigned char rtc_is_updating(void)
static inline unsigned int get_rtc_time(struct rtc_time *time)
- unsigned long uip_watchdog = jiffies;
unsigned char ctrl;
unsigned long flags;
@@ -55,19 +55,15 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
* read RTC once any update in progress is done. The update
- * can take just over 2ms. We wait 10 to 20ms. There is no need to
+ * can take just over 2ms. We wait 20ms. There is no need to
* to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
* If you need to know *exactly* when a second has started, enable
* periodic update complete interrupts, (via ioctl) and then
* immediately read /dev/rtc which will block until you get the IRQ.
* Once the read clears, read the RTC time (again via ioctl). Easy.
- if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100) {
- barrier();
- cpu_relax();
- }
+ if (rtc_is_updating())
+ mdelay(20);
* Only the values that we read from the RTC are set. We leave