aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/dec
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2005-11-02 11:01:15 -0500
committerRalf Baechle <ralf@linux-mips.org>2005-11-07 13:05:38 -0500
commit53c2df2f4ebbc1d8231ca7cc13ac5381230888b1 (patch)
treea7446ec56dd877d77ef7318b4bcdc3d38555ff0a /arch/mips/dec
parente329331aedeca0f2a7e15bd26a829ee1619c05e0 (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')
-rw-r--r--arch/mips/dec/time.c24
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 */
43static 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
40static unsigned long dec_rtc_get_time(void) 54static 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}