tree 0baa7533fc0b96127d03a39b2fa77f2b29564b1c
parent 2f60f8d3573ff90fe5d75a6d11fd2add1248e7d6
author Petr Vandrovec <[EMAIL PROTECTED]> Fri, 05 Aug 2005 15:50:07 +0200
committer Linus Torvalds <[EMAIL PROTECTED]> Fri, 05 Aug 2005 20:57:44 -0700

[PATCH] rtc: msleep() cannot be used from interrupt

Since the beginning of July my Opteron box was randomly crashing and
being rebooted by hardware watchdog.  Today it finally did it in front
of me, and this patch will hopefully fix it.

The problem is that at the end of June (the 28th, to be exact: commit
47f176fdaf8924bc83fddcf9658f2fd3ef60d573, "[PATCH] Using msleep()
instead of HZ") rtc_get_rtc_time was converted to use msleep() instead
of busy waiting.  But rtc_get_rtc_time is used by hpet_rtc_interrupt,
and scheduling is not allowed during interrupt.  So I'm reverting this
part of original change, replacing msleep() back with busy loop.

The original code was busy waiting for up to 20ms, but on my hardware in
the worst case update-in-progress bit was asserted for at most 363
passes through loop (on 2GHz dual Opteron), much less than even one
jiffie, not even talking about 20ms.  So I changed code to just wait
only as long as necessary.  Otherwise when RTC was set to generate
8192Hz timer, it stopped doing anything for 20ms (160 pulses were
skipped!) from time to time, and this is rather suboptimal as far as I
can tell.

Signed-off-by: Petr Vandrovec <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 drivers/char/rtc.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1209,6 +1209,7 @@ static int rtc_proc_open(struct inode *i
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
+       unsigned long uip_watchdog = jiffies;
        unsigned char ctrl;
 #ifdef CONFIG_MACH_DECSTATION
        unsigned int real_year;
@@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *r
         * Once the read clears, read the RTC time (again via ioctl). Easy.
         */
 
-       if (rtc_is_updating() != 0)
-               msleep(20);
+       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
+               barrier();
+               cpu_relax();
+       }
 
        /*
         * Only the values that we read from the RTC are set. We leave
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to