patch-2.2.18 linux/drivers/char/rtc.c
Next file: linux/drivers/char/saa7111.c
Previous file: linux/drivers/char/rio/riotty.c
Back to the patch index
Back to the overall index
- Lines: 257
- Date:
Sat Oct 28 13:46:20 2000
- Orig file:
v2.2.17/drivers/char/rtc.c
- Orig date:
Fri Apr 21 12:46:06 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/drivers/char/rtc.c linux/drivers/char/rtc.c
@@ -42,10 +42,9 @@
/*
* Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
- * interrupts disabled. Due to the index-port/data-port (0x70/0x71)
- * design of the RTC, we don't want two different things trying to
- * get to it at once. (e.g. the periodic 11 min sync from time.c vs.
- * this driver.)
+ * the rtc_lock held. Due to the index-port/data-port (0x70/0x71) design
+ * of the RTC, we don't want two different things trying to get to it at
+ * once. (e.g. the periodic 11 min sync from time.c vs. this driver.)
*/
#include <linux/types.h>
@@ -110,13 +109,15 @@
static unsigned long epoch = 1900; /* year corresponding to 0x00 */
-unsigned char days_in_mo[] =
-{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
* A very tiny interrupt handler. It runs with SA_INTERRUPT set,
- * so that there is no possibility of conflicting with the
- * set_rtc_mmss() call that happens during some timer interrupts.
+ * but there is possibility of conflicting with the set_rtc_mmss()
+ * call (the rtc irq and the timer irq can easily run at the same
+ * time in two different CPUs). So we need to serializes
+ * accesses to the chip with the rtc_lock spinlock that each
+ * architecture should implement in the timer code.
* (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
*/
@@ -131,7 +132,10 @@
rtc_irq_data += 0x100;
rtc_irq_data &= ~0xff;
+ /* runs with irq locally disabled (see SA_INTERRUPT flag). */
+ spin_lock(&rtc_lock);
rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
+ spin_unlock(&rtc_lock);
wake_up_interruptible(&rtc_wait);
if (rtc_status & RTC_TIMER_ON)
@@ -276,8 +280,7 @@
if (sec >= 60)
sec = 0xff;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
RTC_ALWAYS_BCD)
{
@@ -288,7 +291,7 @@
CMOS_WRITE(hrs, RTC_HOURS_ALARM);
CMOS_WRITE(min, RTC_MINUTES_ALARM);
CMOS_WRITE(sec, RTC_SECONDS_ALARM);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
@@ -336,12 +339,11 @@
if ((yrs -= epoch) > 255) /* They are unsigned */
return -EINVAL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
if (yrs > 169) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
return -EINVAL;
}
if (yrs >= 100)
@@ -370,7 +372,7 @@
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
@@ -405,12 +407,11 @@
rtc_freq = arg;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
val |= (16 - tmp);
CMOS_WRITE(val, RTC_FREQ_SELECT);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
#ifdef __alpha__
@@ -465,15 +466,14 @@
unsigned char tmp;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
tmp = CMOS_READ(RTC_CONTROL);
tmp &= ~RTC_PIE;
tmp &= ~RTC_AIE;
tmp &= ~RTC_UIE;
CMOS_WRITE(tmp, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (rtc_status & RTC_TIMER_ON) {
rtc_status &= ~RTC_TIMER_ON;
@@ -546,11 +546,10 @@
while (jiffies - uip_watchdog < 2*HZ/100)
barrier();
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
year = CMOS_READ(RTC_YEAR);
ctrl = CMOS_READ(RTC_CONTROL);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
BCD_TO_BIN(year); /* This should never happen... */
@@ -568,11 +567,10 @@
init_timer(&rtc_irq_timer);
rtc_irq_timer.function = rtc_dropped_irq;
rtc_wait = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
rtc_freq = 1024;
return 0;
}
@@ -596,12 +594,11 @@
printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq);
mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
rtc_irq_data += ((rtc_freq/HZ)<<8);
rtc_irq_data &= ~0xff;
rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
}
/*
@@ -615,11 +612,10 @@
unsigned char batt, ctrl;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
batt = CMOS_READ(RTC_VALID) & RTC_VRT;
ctrl = CMOS_READ(RTC_CONTROL);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
p = buf;
@@ -690,10 +686,9 @@
unsigned long flags;
unsigned char uip;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
return uip;
}
@@ -723,8 +718,7 @@
* RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
* by the RTC when initially set to a non-zero value.
*/
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
@@ -732,7 +726,7 @@
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
ctrl = CMOS_READ(RTC_CONTROL);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
@@ -763,13 +757,12 @@
* Only the values that we read from the RTC are set. That
* means only tm_hour, tm_min, and tm_sec.
*/
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
ctrl = CMOS_READ(RTC_CONTROL);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
@@ -794,13 +787,12 @@
unsigned char val;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
val = CMOS_READ(RTC_CONTROL);
val &= ~bit;
CMOS_WRITE(val, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
rtc_irq_data = 0;
}
@@ -809,12 +801,11 @@
unsigned char val;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&rtc_lock, flags);
val = CMOS_READ(RTC_CONTROL);
val |= bit;
CMOS_WRITE(val, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
rtc_irq_data = 0;
- restore_flags(flags);
+ spin_unlock_irqrestore(&rtc_lock, flags);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)