Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Atsushi Nemoto and committed by
Ralf Baechle
53c2df2f e329331a

+111 -4
+6
arch/mips/ddb5xxx/common/rtc_ds1386.c
··· 41 41 u8 byte; 42 42 u8 temp; 43 43 unsigned int year, month, day, hour, minute, second; 44 + unsigned long flags; 44 45 46 + spin_lock_irqsave(&rtc_lock, flags); 45 47 /* let us freeze external registers */ 46 48 byte = READ_RTC(0xB); 47 49 byte &= 0x3f; ··· 62 60 /* enable time transfer */ 63 61 byte |= 0x80; 64 62 WRITE_RTC(0xB, byte); 63 + spin_unlock_irqrestore(&rtc_lock, flags); 65 64 66 65 /* calc hour */ 67 66 if (temp & 0x40) { ··· 84 81 u8 byte; 85 82 u8 temp; 86 83 u8 year, month, day, hour, minute, second; 84 + unsigned long flags; 87 85 86 + spin_lock_irqsave(&rtc_lock, flags); 88 87 /* let us freeze external registers */ 89 88 byte = READ_RTC(0xB); 90 89 byte &= 0x3f; ··· 138 133 if (second != READ_RTC(0x1)) { 139 134 WRITE_RTC(0x1, second); 140 135 } 136 + spin_unlock_irqrestore(&rtc_lock, flags); 141 137 142 138 return 0; 143 139 }
+22 -2
arch/mips/dec/time.c
··· 37 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 54 static unsigned long dec_rtc_get_time(void) 41 55 { 42 56 unsigned int year, mon, day, hour, min, sec, real_year; 43 57 int i; 58 + unsigned long flags; 44 59 45 60 /* The Linux interpretation of the DS1287 clock register contents: 46 61 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the ··· 64 49 */ 65 50 /* read RTC exactly on falling edge of update flag */ 66 51 for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ 67 - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) 52 + if (dec_rtc_is_updating()) 68 53 break; 69 54 for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ 70 - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) 55 + if (!dec_rtc_is_updating()) 71 56 break; 57 + spin_lock_irqsave(&rtc_lock, flags); 72 58 /* Isn't this overkill? UIP above should guarantee consistency */ 73 59 do { 74 60 sec = CMOS_READ(RTC_SECONDS); ··· 93 77 * of unused BBU RAM locations. 94 78 */ 95 79 real_year = CMOS_READ(RTC_DEC_YEAR); 80 + spin_unlock_irqrestore(&rtc_lock, flags); 96 81 year += real_year - 72 + 2000; 97 82 98 83 return mktime(year, mon, day, hour, min, sec); ··· 112 95 int real_seconds, real_minutes, cmos_minutes; 113 96 unsigned char save_control, save_freq_select; 114 97 98 + /* irq are locally disabled here */ 99 + spin_lock(&rtc_lock); 115 100 /* tell the clock it's being set */ 116 101 save_control = CMOS_READ(RTC_CONTROL); 117 102 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); ··· 160 141 */ 161 142 CMOS_WRITE(save_control, RTC_CONTROL); 162 143 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 144 + spin_unlock(&rtc_lock); 163 145 164 146 return retval; 165 147 }
+6
arch/mips/jmr3927/common/rtc_ds1742.c
··· 57 57 { 58 58 unsigned int year, month, day, hour, minute, second; 59 59 unsigned int century; 60 + unsigned long flags; 60 61 62 + spin_lock_irqsave(&rtc_lock, flags); 61 63 CMOS_WRITE(RTC_READ, RTC_CONTROL); 62 64 second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); 63 65 minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); ··· 69 67 year = BCD2BIN(CMOS_READ(RTC_YEAR)); 70 68 century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); 71 69 CMOS_WRITE(0, RTC_CONTROL); 70 + spin_unlock_irqrestore(&rtc_lock, flags); 72 71 73 72 year += century * 100; 74 73 ··· 84 81 u8 year, month, day, hour, minute, second; 85 82 u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; 86 83 int cmos_century; 84 + unsigned long flags; 87 85 86 + spin_lock_irqsave(&rtc_lock, flags); 88 87 CMOS_WRITE(RTC_READ, RTC_CONTROL); 89 88 cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); 90 89 cmos_minute = (u8)CMOS_READ(RTC_MINUTES); ··· 144 139 145 140 /* RTC_CENTURY and RTC_CONTROL share same address... */ 146 141 CMOS_WRITE(cmos_century, RTC_CONTROL); 142 + spin_unlock_irqrestore(&rtc_lock, flags); 147 143 148 144 return 0; 149 145 }
+9
arch/mips/lasat/ds1603.c
··· 8 8 #include <asm/lasat/lasat.h> 9 9 #include <linux/delay.h> 10 10 #include <asm/lasat/ds1603.h> 11 + #include <asm/time.h> 11 12 12 13 #include "ds1603.h" 13 14 ··· 139 138 unsigned long ds1603_read(void) 140 139 { 141 140 unsigned long word; 141 + unsigned long flags; 142 + 143 + spin_lock_irqsave(&rtc_lock, flags); 142 144 rtc_init_op(); 143 145 rtc_write_byte(READ_TIME_CMD); 144 146 word = rtc_read_word(); 145 147 rtc_end_op(); 148 + spin_unlock_irqrestore(&rtc_lock, flags); 146 149 return word; 147 150 } 148 151 149 152 int ds1603_set(unsigned long time) 150 153 { 154 + unsigned long flags; 155 + 156 + spin_lock_irqsave(&rtc_lock, flags); 151 157 rtc_init_op(); 152 158 rtc_write_byte(SET_TIME_CMD); 153 159 rtc_write_word(time); 154 160 rtc_end_op(); 161 + spin_unlock_irqrestore(&rtc_lock, flags); 155 162 156 163 return 0; 157 164 }
+6
arch/mips/momentum/jaguar_atx/setup.c
··· 149 149 unsigned long m48t37y_get_time(void) 150 150 { 151 151 unsigned int year, month, day, hour, min, sec; 152 + unsigned long flags; 152 153 154 + spin_lock_irqsave(&rtc_lock, flags); 153 155 /* stop the update */ 154 156 rtc_base[0x7ff8] = 0x40; 155 157 ··· 168 166 169 167 /* start the update */ 170 168 rtc_base[0x7ff8] = 0x00; 169 + spin_unlock_irqrestore(&rtc_lock, flags); 171 170 172 171 return mktime(year, month, day, hour, min, sec); 173 172 } ··· 176 173 int m48t37y_set_time(unsigned long sec) 177 174 { 178 175 struct rtc_time tm; 176 + unsigned long flags; 179 177 180 178 /* convert to a more useful format -- note months count from 0 */ 181 179 to_tm(sec, &tm); 182 180 tm.tm_mon += 1; 183 181 182 + spin_lock_irqsave(&rtc_lock, flags); 184 183 /* enable writing */ 185 184 rtc_base[0x7ff8] = 0x80; 186 185 ··· 206 201 207 202 /* disable writing */ 208 203 rtc_base[0x7ff8] = 0x00; 204 + spin_unlock_irqrestore(&rtc_lock, flags); 209 205 210 206 return 0; 211 207 }
+6
arch/mips/momentum/ocelot_3/setup.c
··· 135 135 unsigned long m48t37y_get_time(void) 136 136 { 137 137 unsigned int year, month, day, hour, min, sec; 138 + unsigned long flags; 138 139 140 + spin_lock_irqsave(&rtc_lock, flags); 139 141 /* stop the update */ 140 142 rtc_base[0x7ff8] = 0x40; 141 143 ··· 154 152 155 153 /* start the update */ 156 154 rtc_base[0x7ff8] = 0x00; 155 + spin_unlock_irqrestore(&rtc_lock, flags); 157 156 158 157 return mktime(year, month, day, hour, min, sec); 159 158 } ··· 162 159 int m48t37y_set_time(unsigned long sec) 163 160 { 164 161 struct rtc_time tm; 162 + unsigned long flags; 165 163 166 164 /* convert to a more useful format -- note months count from 0 */ 167 165 to_tm(sec, &tm); 168 166 tm.tm_mon += 1; 169 167 168 + spin_lock_irqsave(&rtc_lock, flags); 170 169 /* enable writing */ 171 170 rtc_base[0x7ff8] = 0x80; 172 171 ··· 192 187 193 188 /* disable writing */ 194 189 rtc_base[0x7ff8] = 0x00; 190 + spin_unlock_irqrestore(&rtc_lock, flags); 195 191 196 192 return 0; 197 193 }
+6
arch/mips/momentum/ocelot_c/setup.c
··· 140 140 unsigned char* rtc_base = (unsigned char*)0xfc800000; 141 141 #endif 142 142 unsigned int year, month, day, hour, min, sec; 143 + unsigned long flags; 143 144 145 + spin_lock_irqsave(&rtc_lock, flags); 144 146 /* stop the update */ 145 147 rtc_base[0x7ff8] = 0x40; 146 148 ··· 159 157 160 158 /* start the update */ 161 159 rtc_base[0x7ff8] = 0x00; 160 + spin_unlock_irqrestore(&rtc_lock, flags); 162 161 163 162 return mktime(year, month, day, hour, min, sec); 164 163 } ··· 172 169 unsigned char* rtc_base = (unsigned char*)0xfc800000; 173 170 #endif 174 171 struct rtc_time tm; 172 + unsigned long flags; 175 173 176 174 /* convert to a more useful format -- note months count from 0 */ 177 175 to_tm(sec, &tm); 178 176 tm.tm_mon += 1; 179 177 178 + spin_lock_irqsave(&rtc_lock, flags); 180 179 /* enable writing */ 181 180 rtc_base[0x7ff8] = 0x80; 182 181 ··· 202 197 203 198 /* disable writing */ 204 199 rtc_base[0x7ff8] = 0x00; 200 + spin_unlock_irqrestore(&rtc_lock, flags); 205 201 206 202 return 0; 207 203 }
+6
arch/mips/pmc-sierra/yosemite/setup.c
··· 73 73 unsigned long m48t37y_get_time(void) 74 74 { 75 75 unsigned int year, month, day, hour, min, sec; 76 + unsigned long flags; 76 77 78 + spin_lock_irqsave(&rtc_lock, flags); 77 79 /* Stop the update to the time */ 78 80 m48t37_base->control = 0x40; 79 81 ··· 90 88 91 89 /* Start the update to the time again */ 92 90 m48t37_base->control = 0x00; 91 + spin_unlock_irqrestore(&rtc_lock, flags); 93 92 94 93 return mktime(year, month, day, hour, min, sec); 95 94 } ··· 98 95 int m48t37y_set_time(unsigned long sec) 99 96 { 100 97 struct rtc_time tm; 98 + unsigned long flags; 101 99 102 100 /* convert to a more useful format -- note months count from 0 */ 103 101 to_tm(sec, &tm); 104 102 tm.tm_mon += 1; 105 103 104 + spin_lock_irqsave(&rtc_lock, flags); 106 105 /* enable writing */ 107 106 m48t37_base->control = 0x80; 108 107 ··· 128 123 129 124 /* disable writing */ 130 125 m48t37_base->control = 0x00; 126 + spin_unlock_irqrestore(&rtc_lock, flags); 131 127 132 128 return 0; 133 129 }
+6
arch/mips/sgi-ip22/ip22-time.c
··· 35 35 { 36 36 unsigned int yrs, mon, day, hrs, min, sec; 37 37 unsigned int save_control; 38 + unsigned long flags; 38 39 40 + spin_lock_irqsave(&rtc_lock, flags); 39 41 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; 40 42 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; 41 43 ··· 49 47 yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); 50 48 51 49 hpc3c0->rtcregs[RTC_CMD] = save_control; 50 + spin_unlock_irqrestore(&rtc_lock, flags); 52 51 53 52 if (yrs < 45) 54 53 yrs += 30; ··· 63 60 { 64 61 struct rtc_time tm; 65 62 unsigned int save_control; 63 + unsigned long flags; 66 64 67 65 to_tm(tim, &tm); 68 66 ··· 72 68 if (tm.tm_year >= 100) 73 69 tm.tm_year -= 100; 74 70 71 + spin_lock_irqsave(&rtc_lock, flags); 75 72 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; 76 73 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; 77 74 ··· 85 80 hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; 86 81 87 82 hpc3c0->rtcregs[RTC_CMD] = save_control; 83 + spin_unlock_irqrestore(&rtc_lock, flags); 88 84 89 85 return 0; 90 86 }
+7
arch/mips/sibyte/swarm/rtc_m41t81.c
··· 144 144 int m41t81_set_time(unsigned long t) 145 145 { 146 146 struct rtc_time tm; 147 + unsigned long flags; 147 148 148 149 to_tm(t, &tm); 149 150 ··· 154 153 * believe we should finish writing min within a second. 155 154 */ 156 155 156 + spin_lock_irqsave(&rtc_lock, flags); 157 157 tm.tm_sec = BIN2BCD(tm.tm_sec); 158 158 m41t81_write(M41T81REG_SC, tm.tm_sec); 159 159 ··· 182 180 tm.tm_year %= 100; 183 181 tm.tm_year = BIN2BCD(tm.tm_year); 184 182 m41t81_write(M41T81REG_YR, tm.tm_year); 183 + spin_unlock_irqrestore(&rtc_lock, flags); 185 184 186 185 return 0; 187 186 } ··· 190 187 unsigned long m41t81_get_time(void) 191 188 { 192 189 unsigned int year, mon, day, hour, min, sec; 190 + unsigned long flags; 193 191 194 192 /* 195 193 * min is valid if two reads of sec are the same. 196 194 */ 197 195 for (;;) { 196 + spin_lock_irqsave(&rtc_lock, flags); 198 197 sec = m41t81_read(M41T81REG_SC); 199 198 min = m41t81_read(M41T81REG_MN); 200 199 if (sec == m41t81_read(M41T81REG_SC)) break; 200 + spin_unlock_irqrestore(&rtc_lock, flags); 201 201 } 202 202 hour = m41t81_read(M41T81REG_HR) & 0x3f; 203 203 day = m41t81_read(M41T81REG_DT); 204 204 mon = m41t81_read(M41T81REG_MO); 205 205 year = m41t81_read(M41T81REG_YR); 206 + spin_unlock_irqrestore(&rtc_lock, flags); 206 207 207 208 sec = BCD2BIN(sec); 208 209 min = BCD2BIN(min);
+6
arch/mips/sibyte/swarm/rtc_xicor1241.c
··· 113 113 { 114 114 struct rtc_time tm; 115 115 int tmp; 116 + unsigned long flags; 116 117 117 118 to_tm(t, &tm); 118 119 120 + spin_lock_irqsave(&rtc_lock, flags); 119 121 /* unlock writes to the CCR */ 120 122 xicor_write(X1241REG_SR, X1241REG_SR_WEL); 121 123 xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); ··· 162 160 xicor_write(X1241REG_HR, tmp); 163 161 164 162 xicor_write(X1241REG_SR, 0); 163 + spin_unlock_irqrestore(&rtc_lock, flags); 165 164 166 165 return 0; 167 166 } ··· 170 167 unsigned long xicor_get_time(void) 171 168 { 172 169 unsigned int year, mon, day, hour, min, sec, y2k; 170 + unsigned long flags; 173 171 172 + spin_lock_irqsave(&rtc_lock, flags); 174 173 sec = xicor_read(X1241REG_SC); 175 174 min = xicor_read(X1241REG_MN); 176 175 hour = xicor_read(X1241REG_HR); ··· 188 183 mon = xicor_read(X1241REG_MO); 189 184 year = xicor_read(X1241REG_YR); 190 185 y2k = xicor_read(X1241REG_Y2K); 186 + spin_unlock_irqrestore(&rtc_lock, flags); 191 187 192 188 sec = BCD2BIN(sec); 193 189 min = BCD2BIN(min);
+22 -2
include/asm-mips/mc146818-time.h
··· 33 33 int real_seconds, real_minutes, cmos_minutes; 34 34 unsigned char save_control, save_freq_select; 35 35 int retval = 0; 36 + unsigned long flags; 36 37 38 + spin_lock_irqsave(&rtc_lock, flags); 37 39 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ 38 40 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 39 41 ··· 81 79 */ 82 80 CMOS_WRITE(save_control, RTC_CONTROL); 83 81 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 82 + spin_unlock_irqrestore(&rtc_lock, flags); 84 83 85 84 return retval; 85 + } 86 + 87 + /* 88 + * Returns true if a clock update is in progress 89 + */ 90 + static inline unsigned char rtc_is_updating(void) 91 + { 92 + unsigned char uip; 93 + unsigned long flags; 94 + 95 + spin_lock_irqsave(&rtc_lock, flags); 96 + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); 97 + spin_unlock_irqrestore(&rtc_lock, flags); 98 + return uip; 86 99 } 87 100 88 101 static inline unsigned long mc146818_get_cmos_time(void) 89 102 { 90 103 unsigned int year, mon, day, hour, min, sec; 91 104 int i; 105 + unsigned long flags; 92 106 93 107 /* 94 108 * The Linux interpretation of the CMOS clock register contents: ··· 115 97 116 98 /* read RTC exactly on falling edge of update flag */ 117 99 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ 118 - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) 100 + if (rtc_is_updating()) 119 101 break; 120 102 for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ 121 - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) 103 + if (!rtc_is_updating()) 122 104 break; 123 105 106 + spin_lock_irqsave(&rtc_lock, flags); 124 107 do { /* Isn't this overkill ? UIP above should guarantee consistency */ 125 108 sec = CMOS_READ(RTC_SECONDS); 126 109 min = CMOS_READ(RTC_MINUTES); ··· 139 120 BCD_TO_BIN(mon); 140 121 BCD_TO_BIN(year); 141 122 } 123 + spin_unlock_irqrestore(&rtc_lock, flags); 142 124 year = mc146818_decode_year(year); 143 125 144 126 return mktime(year, mon, day, hour, min, sec);
+3
include/asm-mips/time.h
··· 20 20 #include <linux/linkage.h> 21 21 #include <linux/ptrace.h> 22 22 #include <linux/rtc.h> 23 + #include <linux/spinlock.h> 24 + 25 + extern spinlock_t rtc_lock; 23 26 24 27 /* 25 28 * RTC ops. By default, they point to no-RTC functions.