make queue_delayed_work() friendly to flush_fork()
[powerpc.git] / kernel / time / ntp.c
index 65223b7..cb25649 100644 (file)
@@ -24,24 +24,41 @@ static u64 tick_length, tick_length_base;
 
 #define MAX_TICKADJ            500             /* microsecs */
 #define MAX_TICKADJ_SCALED     (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
-                                 TICK_LENGTH_SHIFT) / HZ)
+                                 TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
 
 /*
  * phase-lock loop variables
  */
 /* TIME_ERROR prevents overwriting the CMOS clock */
-int time_state = TIME_OK;              /* clock synchronization status */
+static int time_state = TIME_OK;       /* clock synchronization status */
 int time_status = STA_UNSYNC;          /* clock status bits            */
-long time_offset;                      /* time adjustment (ns)         */
-long time_constant = 2;                        /* pll time constant            */
-long time_tolerance = MAXFREQ;         /* frequency tolerance (ppm)    */
-long time_precision = 1;               /* clock precision (us)         */
+static s64 time_offset;                /* time adjustment (ns)         */
+static long time_constant = 2;         /* pll time constant            */
 long time_maxerror = NTP_PHASE_LIMIT;  /* maximum error (us)           */
 long time_esterror = NTP_PHASE_LIMIT;  /* estimated error (us)         */
 long time_freq;                                /* frequency offset (scaled ppm)*/
-long time_reftime;                     /* time at last adjustment (s)  */
+static long time_reftime;              /* time at last adjustment (s)  */
 long time_adjust;
 
+#define CLOCK_TICK_OVERFLOW    (LATCH * HZ - CLOCK_TICK_RATE)
+#define CLOCK_TICK_ADJUST      (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
+                                       (s64)CLOCK_TICK_RATE)
+
+static void ntp_update_frequency(void)
+{
+       u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
+                               << TICK_LENGTH_SHIFT;
+       second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
+       second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+
+       tick_length_base = second_length;
+
+       do_div(second_length, HZ);
+       tick_nsec = second_length >> TICK_LENGTH_SHIFT;
+
+       do_div(tick_length_base, NTP_INTERVAL_FREQ);
+}
+
 /**
  * ntp_clear - Clears the NTP state variables
  *
@@ -60,20 +77,6 @@ void ntp_clear(void)
        time_offset = 0;
 }
 
-#define CLOCK_TICK_OVERFLOW    (LATCH * HZ - CLOCK_TICK_RATE)
-#define CLOCK_TICK_ADJUST      (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / (s64)CLOCK_TICK_RATE)
-
-void ntp_update_frequency(void)
-{
-       tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
-       tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
-       tick_length_base += ((s64)time_freq * NSEC_PER_USEC) << (TICK_LENGTH_SHIFT - SHIFT_USEC);
-
-       do_div(tick_length_base, HZ);
-
-       tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
-}
-
 /*
  * this routine handles the overflow of the microsecond field
  *
@@ -87,7 +90,7 @@ void second_overflow(void)
        long time_adj;
 
        /* Bump the maxerror field */
-       time_maxerror += time_tolerance >> SHIFT_USEC;
+       time_maxerror += MAXFREQ >> SHIFT_USEC;
        if (time_maxerror > NTP_PHASE_LIMIT) {
                time_maxerror = NTP_PHASE_LIMIT;
                time_status |= STA_UNSYNC;
@@ -146,18 +149,11 @@ void second_overflow(void)
        }
 
        /*
-        * Compute the phase adjustment for the next second. In PLL mode, the
-        * offset is reduced by a fixed factor times the time constant. In FLL
-        * mode the offset is used directly. In either mode, the maximum phase
-        * adjustment for each second is clamped so as to spread the adjustment
-        * over not more than the number of seconds between updates.
+        * Compute the phase adjustment for the next second. The offset is
+        * reduced by a fixed factor times the time constant.
         */
        tick_length = tick_length_base;
-       time_adj = time_offset;
-       if (!(time_status & STA_FLL))
-               time_adj = shift_right(time_adj, SHIFT_KG + time_constant);
-       time_adj = min(time_adj, -((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
-       time_adj = max(time_adj, ((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
+       time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
        time_offset -= time_adj;
        tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
 
@@ -169,9 +165,9 @@ void second_overflow(void)
                        time_adjust += MAX_TICKADJ;
                        tick_length -= MAX_TICKADJ_SCALED;
                } else {
-                       time_adjust = 0;
                        tick_length += (s64)(time_adjust * NSEC_PER_USEC /
-                                            HZ) << TICK_LENGTH_SHIFT;
+                                       NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
+                       time_adjust = 0;
                }
        }
 }
@@ -200,7 +196,8 @@ void __attribute__ ((weak)) notify_arch_cmos_timer(void)
  */
 int do_adjtimex(struct timex *txc)
 {
-       long ltemp, mtemp, save_adjust;
+       long mtemp, save_adjust, rem;
+       s64 freq_adj, temp64;
        int result;
 
        /* In order to modify anything, you gotta be super-user! */
@@ -246,7 +243,8 @@ int do_adjtimex(struct timex *txc)
                    result = -EINVAL;
                    goto leave;
                }
-               time_freq = txc->freq;
+               time_freq = ((s64)txc->freq * NSEC_PER_USEC)
+                               >> (SHIFT_USEC - SHIFT_NSEC);
            }
 
            if (txc->modes & ADJ_MAXERROR) {
@@ -270,7 +268,7 @@ int do_adjtimex(struct timex *txc)
                    result = -EINVAL;
                    goto leave;
                }
-               time_constant = txc->constant;
+               time_constant = min(txc->constant + 4, (long)MAXTC);
            }
 
            if (txc->modes & ADJ_OFFSET) {      /* values checked earlier */
@@ -279,14 +277,14 @@ int do_adjtimex(struct timex *txc)
                    time_adjust = txc->offset;
                }
                else if (time_status & STA_PLL) {
-                   ltemp = txc->offset;
+                   time_offset = txc->offset * NSEC_PER_USEC;
 
                    /*
                     * Scale the phase adjustment and
                     * clamp to the operating range.
                     */
-                   time_offset = min(ltemp, MAXPHASE);
-                   time_offset = max(time_offset, -MAXPHASE);
+                   time_offset = min(time_offset, (s64)MAXPHASE * NSEC_PER_USEC);
+                   time_offset = max(time_offset, (s64)-MAXPHASE * NSEC_PER_USEC);
 
                    /*
                     * Select whether the frequency is to be controlled
@@ -298,24 +296,28 @@ int do_adjtimex(struct timex *txc)
                        time_reftime = xtime.tv_sec;
                    mtemp = xtime.tv_sec - time_reftime;
                    time_reftime = xtime.tv_sec;
-                   if (time_status & STA_FLL) {
-                       if (mtemp >= MINSEC) {
-                           ltemp = ((time_offset << 12) / mtemp) << (SHIFT_USEC - 12);
-                           time_freq += shift_right(ltemp, SHIFT_KH);
-                       } else /* calibration interval too short (p. 12) */
-                               result = TIME_ERROR;
-                   } else {    /* PLL mode */
-                       if (mtemp < MAXSEC) {
-                           ltemp *= mtemp;
-                           time_freq += shift_right(ltemp,(time_constant +
-                                                      time_constant +
-                                                      SHIFT_KF - SHIFT_USEC));
-                       } else /* calibration interval too long (p. 12) */
-                               result = TIME_ERROR;
+
+                   freq_adj = time_offset * mtemp;
+                   freq_adj = shift_right(freq_adj, time_constant * 2 +
+                                          (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
+                   if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
+                       temp64 = time_offset << (SHIFT_NSEC - SHIFT_FLL);
+                       if (time_offset < 0) {
+                           temp64 = -temp64;
+                           do_div(temp64, mtemp);
+                           freq_adj -= temp64;
+                       } else {
+                           do_div(temp64, mtemp);
+                           freq_adj += temp64;
+                       }
                    }
-                   time_freq = min(time_freq, time_tolerance);
-                   time_freq = max(time_freq, -time_tolerance);
-                   time_offset = (time_offset * NSEC_PER_USEC / HZ) << SHIFT_UPDATE;
+                   freq_adj += time_freq;
+                   freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
+                   time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
+                   time_offset = div_long_long_rem_signed(time_offset,
+                                                          NTP_INTERVAL_FREQ,
+                                                          &rem);
+                   time_offset <<= SHIFT_UPDATE;
                } /* STA_PLL */
            } /* txc->modes & ADJ_OFFSET */
            if (txc->modes & ADJ_TICK)
@@ -328,16 +330,18 @@ leave:    if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
                result = TIME_ERROR;
 
        if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
-           txc->offset    = save_adjust;
+               txc->offset = save_adjust;
        else
-           txc->offset    = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
-       txc->freq          = time_freq;
+               txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) *
+                               NTP_INTERVAL_FREQ / 1000;
+       txc->freq          = (time_freq / NSEC_PER_USEC) <<
+                               (SHIFT_USEC - SHIFT_NSEC);
        txc->maxerror      = time_maxerror;
        txc->esterror      = time_esterror;
        txc->status        = time_status;
        txc->constant      = time_constant;
-       txc->precision     = time_precision;
-       txc->tolerance     = time_tolerance;
+       txc->precision     = 1;
+       txc->tolerance     = MAXFREQ;
        txc->tick          = tick_usec;
 
        /* PPS is not implemented, so these are zero */