|
@@ -122,7 +122,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
|
|
|
static unsigned long __cpuinit calibrate_delay_converge(void)
|
|
|
{
|
|
|
/* First stage - slowly accelerate to find initial bounds */
|
|
|
- unsigned long lpj, ticks, loopadd, chop_limit;
|
|
|
+ unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
|
|
|
int trials = 0, band = 0, trial_in_band = 0;
|
|
|
|
|
|
lpj = (1<<12);
|
|
@@ -146,14 +146,18 @@ static unsigned long __cpuinit calibrate_delay_converge(void)
|
|
|
* the largest likely undershoot. This defines our chop bounds.
|
|
|
*/
|
|
|
trials -= band;
|
|
|
- loopadd = lpj * band;
|
|
|
- lpj *= trials;
|
|
|
- chop_limit = lpj >> (LPS_PREC + 1);
|
|
|
+ loopadd_base = lpj * band;
|
|
|
+ lpj_base = lpj * trials;
|
|
|
+
|
|
|
+recalibrate:
|
|
|
+ lpj = lpj_base;
|
|
|
+ loopadd = loopadd_base;
|
|
|
|
|
|
/*
|
|
|
* Do a binary approximation to get lpj set to
|
|
|
* equal one clock (up to LPS_PREC bits)
|
|
|
*/
|
|
|
+ chop_limit = lpj >> LPS_PREC;
|
|
|
while (loopadd > chop_limit) {
|
|
|
lpj += loopadd;
|
|
|
ticks = jiffies;
|
|
@@ -165,6 +169,16 @@ static unsigned long __cpuinit calibrate_delay_converge(void)
|
|
|
lpj -= loopadd;
|
|
|
loopadd >>= 1;
|
|
|
}
|
|
|
+ /*
|
|
|
+ * If we incremented every single time possible, presume we've
|
|
|
+ * massively underestimated initially, and retry with a higher
|
|
|
+ * start, and larger range. (Only seen on x86_64, due to SMIs)
|
|
|
+ */
|
|
|
+ if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
|
|
|
+ lpj_base = lpj;
|
|
|
+ loopadd_base <<= 2;
|
|
|
+ goto recalibrate;
|
|
|
+ }
|
|
|
|
|
|
return lpj;
|
|
|
}
|