ia64/xen-unstable

changeset 652:784f6ddcee8e

bitkeeper revision 1.366.1.1 (3f1bbc10yTVXbX8BeEQcUVKQmXTucQ)

time.c:
Fix reading of CMOS time -- beware the update-in-progress flag.
author kaf24@scramble.cl.cam.ac.uk
date Mon Jul 21 10:10:24 2003 +0000 (2003-07-21)
parents 9080b9366dbc
children a7bfe57ca27f
files xen/arch/i386/time.c
line diff
     1.1 --- a/xen/arch/i386/time.c	Fri Jul 18 15:03:00 2003 +0000
     1.2 +++ b/xen/arch/i386/time.c	Mon Jul 21 10:10:24 2003 +0000
     1.3 @@ -229,22 +229,24 @@ static unsigned long __get_cmos_time(voi
     1.4      return mktime(year, mon, day, hour, min, sec);
     1.5  }
     1.6  
     1.7 -/*
     1.8 - * This version doesn't wait for start of a new second, but double reads
     1.9 - * to ensure we get a consistent view of all CMOS values.
    1.10 - */
    1.11 -static unsigned long get_cmos_time_fast(void)
    1.12 +/* This version is fast: it bails if there's an update in progress. */
    1.13 +static unsigned long maybe_get_cmos_time(void)
    1.14  {
    1.15 -    unsigned long a, b, flags;
    1.16 +    unsigned long ct, retval = 0, flags;
    1.17  
    1.18      spin_lock_irqsave(&rtc_lock, flags);
    1.19  
    1.20 -    a = __get_cmos_time();
    1.21 -    while ( (b = __get_cmos_time()) != a ) a = b;
    1.22 +    if ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
    1.23 +        goto out;
    1.24 +
    1.25 +    ct = __get_cmos_time();
    1.26  
    1.27 +    if ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
    1.28 +        retval = ct;
    1.29 +    
    1.30 + out:
    1.31      spin_unlock_irqrestore(&rtc_lock, flags);
    1.32 -
    1.33 -    return a;
    1.34 +    return retval;
    1.35  }
    1.36  
    1.37  /* the more accurate version waits for a change */
    1.38 @@ -421,7 +423,12 @@ static void update_time(unsigned long fo
    1.39   * - index 1 -> frequency as determined during calibration
    1.40   * - index 2 -> go faster
    1.41   */
    1.42 -#define UPDATE_PERIOD   SECONDS(50)
    1.43 +/*
    1.44 + * NB. The period is not a whole number of seconds since we want to avoid
    1.45 + * being in sync with the CMOS update-in-progress flag, which causes this
    1.46 + * routine to bail.
    1.47 + */
    1.48 +#define UPDATE_PERIOD   MILLISECS(50200)
    1.49  static struct ac_timer scale_timer;
    1.50  static unsigned long   init_cmos_time;
    1.51  static u64             cpu_freqs[3];
    1.52 @@ -435,7 +442,8 @@ static void update_scale(unsigned long f
    1.53      u64            scale;
    1.54      int            freq_index;
    1.55  
    1.56 -    cmos_time = get_cmos_time_fast();
    1.57 +    if ( (cmos_time = maybe_get_cmos_time()) == 0 )
    1.58 +        return;
    1.59  
    1.60      spin_lock_irqsave(&stime_lock, flags);
    1.61      now  = __get_s_time();
    1.62 @@ -467,7 +475,6 @@ static void update_scale(unsigned long f
    1.63      TRC(printk(" %ds[%d] ", dt, freq_index));
    1.64  }
    1.65  
    1.66 -
    1.67  /***************************************************************************
    1.68   * Init Xeno Time
    1.69   * This has to be done after all CPUs have been booted
    1.70 @@ -479,7 +486,6 @@ int __init init_xeno_time()
    1.71      u64      scale;      /* scale factor */
    1.72      s64      freq_off;
    1.73  
    1.74 -
    1.75      spin_lock_init(&stime_lock);
    1.76      spin_lock_init(&wctime_lock);
    1.77  
    1.78 @@ -493,7 +499,6 @@ int __init init_xeno_time()
    1.79      st_scale_f = scale & 0xffffffff;
    1.80      st_scale_i = scale >> 32;
    1.81  
    1.82 -    
    1.83      /* calculate adjusted frequencies */
    1.84      freq_off  = cpu_freq/1000; /* .1%  */
    1.85      cpu_freqs[0] = cpu_freq + freq_off;