diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2005-11-02 11:01:15 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-11-07 13:05:38 -0500 |
commit | 53c2df2f4ebbc1d8231ca7cc13ac5381230888b1 (patch) | |
tree | a7446ec56dd877d77ef7318b4bcdc3d38555ff0a /arch/mips/dec/time.c | |
parent | e329331aedeca0f2a7e15bd26a829ee1619c05e0 (diff) |
Use rtc_lock to protect RTC operations
Many RTC routines were not protected against each other, so there are
potential races, for example, ntp-update against /dev/rtc. This patch
fixes them using rtc_lock.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/dec/time.c')
-rw-r--r-- | arch/mips/dec/time.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index dc7091caa7aa..174822344131 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
@@ -37,10 +37,25 @@ | |||
37 | #include <asm/dec/machtype.h> | 37 | #include <asm/dec/machtype.h> |
38 | 38 | ||
39 | 39 | ||
40 | /* | ||
41 | * Returns true if a clock update is in progress | ||
42 | */ | ||
43 | static inline unsigned char dec_rtc_is_updating(void) | ||
44 | { | ||
45 | unsigned char uip; | ||
46 | unsigned long flags; | ||
47 | |||
48 | spin_lock_irqsave(&rtc_lock, flags); | ||
49 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
50 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
51 | return uip; | ||
52 | } | ||
53 | |||
40 | static unsigned long dec_rtc_get_time(void) | 54 | static unsigned long dec_rtc_get_time(void) |
41 | { | 55 | { |
42 | unsigned int year, mon, day, hour, min, sec, real_year; | 56 | unsigned int year, mon, day, hour, min, sec, real_year; |
43 | int i; | 57 | int i; |
58 | unsigned long flags; | ||
44 | 59 | ||
45 | /* The Linux interpretation of the DS1287 clock register contents: | 60 | /* The Linux interpretation of the DS1287 clock register contents: |
46 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | 61 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the |
@@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void) | |||
49 | */ | 64 | */ |
50 | /* read RTC exactly on falling edge of update flag */ | 65 | /* read RTC exactly on falling edge of update flag */ |
51 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ | 66 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ |
52 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | 67 | if (dec_rtc_is_updating()) |
53 | break; | 68 | break; |
54 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ | 69 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ |
55 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | 70 | if (!dec_rtc_is_updating()) |
56 | break; | 71 | break; |
72 | spin_lock_irqsave(&rtc_lock, flags); | ||
57 | /* Isn't this overkill? UIP above should guarantee consistency */ | 73 | /* Isn't this overkill? UIP above should guarantee consistency */ |
58 | do { | 74 | do { |
59 | sec = CMOS_READ(RTC_SECONDS); | 75 | sec = CMOS_READ(RTC_SECONDS); |
@@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void) | |||
77 | * of unused BBU RAM locations. | 93 | * of unused BBU RAM locations. |
78 | */ | 94 | */ |
79 | real_year = CMOS_READ(RTC_DEC_YEAR); | 95 | real_year = CMOS_READ(RTC_DEC_YEAR); |
96 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
80 | year += real_year - 72 + 2000; | 97 | year += real_year - 72 + 2000; |
81 | 98 | ||
82 | return mktime(year, mon, day, hour, min, sec); | 99 | return mktime(year, mon, day, hour, min, sec); |
@@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime) | |||
95 | int real_seconds, real_minutes, cmos_minutes; | 112 | int real_seconds, real_minutes, cmos_minutes; |
96 | unsigned char save_control, save_freq_select; | 113 | unsigned char save_control, save_freq_select; |
97 | 114 | ||
115 | /* irq are locally disabled here */ | ||
116 | spin_lock(&rtc_lock); | ||
98 | /* tell the clock it's being set */ | 117 | /* tell the clock it's being set */ |
99 | save_control = CMOS_READ(RTC_CONTROL); | 118 | save_control = CMOS_READ(RTC_CONTROL); |
100 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); | 119 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); |
@@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime) | |||
141 | */ | 160 | */ |
142 | CMOS_WRITE(save_control, RTC_CONTROL); | 161 | CMOS_WRITE(save_control, RTC_CONTROL); |
143 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 162 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
163 | spin_unlock(&rtc_lock); | ||
144 | 164 | ||
145 | return retval; | 165 | return retval; |
146 | } | 166 | } |