rtc: fix deadlock

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>

+4 -8
+4 -8
include/asm-generic/rtc.h
··· 15 15 #include <linux/mc146818rtc.h> 16 16 #include <linux/rtc.h> 17 17 #include <linux/bcd.h> 18 + #include <linux/delay.h> 18 19 19 20 #define RTC_PIE 0x40 /* periodic interrupt enable */ 20 21 #define RTC_AIE 0x20 /* alarm interrupt enable */ ··· 44 43 45 44 static inline unsigned int get_rtc_time(struct rtc_time *time) 46 45 { 47 - unsigned long uip_watchdog = jiffies; 48 46 unsigned char ctrl; 49 47 unsigned long flags; 50 48 ··· 53 53 54 54 /* 55 55 * read RTC once any update in progress is done. The update 56 - * can take just over 2ms. We wait 10 to 20ms. There is no need to 56 + * can take just over 2ms. We wait 20ms. There is no need to 57 57 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. 58 58 * If you need to know *exactly* when a second has started, enable 59 59 * periodic update complete interrupts, (via ioctl) and then 60 60 * immediately read /dev/rtc which will block until you get the IRQ. 61 61 * Once the read clears, read the RTC time (again via ioctl). Easy. 62 62 */ 63 - 64 - if (rtc_is_updating() != 0) 65 - while (jiffies - uip_watchdog < 2*HZ/100) { 66 - barrier(); 67 - cpu_relax(); 68 - } 63 + if (rtc_is_updating()) 64 + mdelay(20); 69 65 70 66 /* 71 67 * Only the values that we read from the RTC are set. We leave