]> Pileus Git - ~andy/linux/blobdiff - init/calibrate.c
calibrate: home in on correct lpj value more quickly
[~andy/linux] / init / calibrate.c
index b71643a7acae8e9eba4c3cfe16b02a343f2098c8..f9000dfbe2271eaaca8b3e52bf05365be92a1cc7 100644 (file)
@@ -110,8 +110,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
 
 /*
  * This is the number of bits of precision for the loops_per_jiffy.  Each
- * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
- * better than 1%
+ * time we refine our estimate after the first takes 1.5/HZ seconds, so try
+ * to start with a good estimate.
  * For the boot cpu we can skip the delay calibration and assign it a value
  * calculated based on the timer frequency.
  * For the rest of the CPUs we cannot assume that the timer frequency is same as
@@ -121,38 +121,49 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
 
 static unsigned long __cpuinit calibrate_delay_converge(void)
 {
-       unsigned long lpj, ticks, loopbit;
-       int lps_precision = LPS_PREC;
+       /* First stage - slowly accelerate to find initial bounds */
+       unsigned long lpj, ticks, loopadd, chop_limit;
+       int trials = 0, band = 0, trial_in_band = 0;
 
        lpj = (1<<12);
-       while ((lpj <<= 1) != 0) {
-               /* wait for "start of" clock tick */
-               ticks = jiffies;
-               while (ticks == jiffies)
-                       /* nothing */;
-               /* Go .. */
-               ticks = jiffies;
-               __delay(lpj);
-               ticks = jiffies - ticks;
-               if (ticks)
-                       break;
-       }
+
+       /* wait for "start of" clock tick */
+       ticks = jiffies;
+       while (ticks == jiffies)
+               ; /* nothing */
+       /* Go .. */
+       ticks = jiffies;
+       do {
+               if (++trial_in_band == (1<<band)) {
+                       ++band;
+                       trial_in_band = 0;
+               }
+               __delay(lpj * band);
+               trials += band;
+       } while (ticks == jiffies);
+       /*
+        * We overshot, so retreat to a clear underestimate. Then estimate
+        * the largest likely undershoot. This defines our chop bounds.
+        */
+       trials -= band;
+       loopadd = lpj * band;
+       lpj *= trials;
+       chop_limit = lpj >> (LPS_PREC + 1);
 
        /*
         * Do a binary approximation to get lpj set to
-        * equal one clock (up to lps_precision bits)
+        * equal one clock (up to LPS_PREC bits)
         */
-       lpj >>= 1;
-       loopbit = lpj;
-       while (lps_precision-- && (loopbit >>= 1)) {
-               lpj |= loopbit;
+       while (loopadd > chop_limit) {
+               lpj += loopadd;
                ticks = jiffies;
                while (ticks == jiffies)
-                       /* nothing */;
+                       ; /* nothing */
                ticks = jiffies;
                __delay(lpj);
                if (jiffies != ticks)   /* longer than 1 tick */
-                       lpj &= ~loopbit;
+                       lpj -= loopadd;
+               loopadd >>= 1;
        }
 
        return lpj;