diff -urN 2.3.51pre2/arch/alpha/kernel/alpha_ksyms.c rtc/arch/alpha/kernel/alpha_ksyms.c --- 2.3.51pre2/arch/alpha/kernel/alpha_ksyms.c Sun Feb 27 06:19:41 2000 +++ rtc/arch/alpha/kernel/alpha_ksyms.c Fri Mar 10 04:58:33 2000 @@ -37,6 +37,7 @@ extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern spinlock_t kernel_flag; +extern spinlock_t rtc_lock; /* these are C runtime functions with special calling conventions: */ extern void __divl (void); @@ -201,6 +202,8 @@ EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(__local_irq_count); #endif /* __SMP__ */ + +EXPORT_SYMBOL(rtc_lock); /* * The following are special because they're not called diff -urN 2.3.51pre2/arch/alpha/kernel/time.c rtc/arch/alpha/kernel/time.c --- 2.3.51pre2/arch/alpha/kernel/time.c Fri Mar 3 02:19:23 2000 +++ rtc/arch/alpha/kernel/time.c Fri Mar 10 04:57:56 2000 @@ -48,6 +48,7 @@ static int set_rtc_mmss(unsigned long); +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; /* * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting @@ -406,6 +407,8 @@ int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* irq are locally disabled here */ + spin_lock(&rtc_lock); /* Tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -455,6 +458,7 @@ */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } diff -urN 2.3.51pre2/arch/i386/kernel/i386_ksyms.c rtc/arch/i386/kernel/i386_ksyms.c --- 2.3.51pre2/arch/i386/kernel/i386_ksyms.c Sun Feb 27 06:19:41 2000 +++ rtc/arch/i386/kernel/i386_ksyms.c Fri Mar 10 04:58:57 2000 @@ -25,6 +25,7 @@ extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); +extern spinlock_t rtc_lock; #ifdef CONFIG_SMP extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); @@ -145,3 +146,5 @@ EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(irq_stat); + +EXPORT_SYMBOL(rtc_lock); diff -urN 2.3.51pre2/arch/i386/kernel/time.c rtc/arch/i386/kernel/time.c --- 2.3.51pre2/arch/i386/kernel/time.c Sun Jan 30 15:43:27 2000 +++ rtc/arch/i386/kernel/time.c Fri Mar 10 04:57:56 2000 @@ -80,6 +80,8 @@ extern rwlock_t xtime_lock; +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; + static inline unsigned long do_fast_gettimeoffset(void) { register unsigned long eax, edx; @@ -302,6 +304,8 @@ int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* gets recalled with irq locally disabled */ + spin_lock(&rtc_lock); save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -347,6 +351,7 @@ */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } diff -urN 2.3.51pre2/drivers/char/rtc.c rtc/drivers/char/rtc.c --- 2.3.51pre2/drivers/char/rtc.c Sun Feb 27 06:19:42 2000 +++ rtc/drivers/char/rtc.c Fri Mar 10 05:01:20 2000 @@ -87,7 +87,7 @@ static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); -static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +extern spinlock_t rtc_lock; static struct timer_list rtc_irq_timer; @@ -141,8 +141,11 @@ #ifndef __alpha__ /* * 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.) */