diff options
Diffstat (limited to 'init/calibrate.c')
-rw-r--r-- | init/calibrate.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/init/calibrate.c b/init/calibrate.c index f9000dfbe227..76ac9194cbc4 100644 --- a/init/calibrate.c +++ b/init/calibrate.c | |||
@@ -122,7 +122,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} | |||
122 | static unsigned long __cpuinit calibrate_delay_converge(void) | 122 | static unsigned long __cpuinit calibrate_delay_converge(void) |
123 | { | 123 | { |
124 | /* First stage - slowly accelerate to find initial bounds */ | 124 | /* First stage - slowly accelerate to find initial bounds */ |
125 | unsigned long lpj, ticks, loopadd, chop_limit; | 125 | unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit; |
126 | int trials = 0, band = 0, trial_in_band = 0; | 126 | int trials = 0, band = 0, trial_in_band = 0; |
127 | 127 | ||
128 | lpj = (1<<12); | 128 | lpj = (1<<12); |
@@ -146,14 +146,18 @@ static unsigned long __cpuinit calibrate_delay_converge(void) | |||
146 | * the largest likely undershoot. This defines our chop bounds. | 146 | * the largest likely undershoot. This defines our chop bounds. |
147 | */ | 147 | */ |
148 | trials -= band; | 148 | trials -= band; |
149 | loopadd = lpj * band; | 149 | loopadd_base = lpj * band; |
150 | lpj *= trials; | 150 | lpj_base = lpj * trials; |
151 | chop_limit = lpj >> (LPS_PREC + 1); | 151 | |
152 | recalibrate: | ||
153 | lpj = lpj_base; | ||
154 | loopadd = loopadd_base; | ||
152 | 155 | ||
153 | /* | 156 | /* |
154 | * Do a binary approximation to get lpj set to | 157 | * Do a binary approximation to get lpj set to |
155 | * equal one clock (up to LPS_PREC bits) | 158 | * equal one clock (up to LPS_PREC bits) |
156 | */ | 159 | */ |
160 | chop_limit = lpj >> LPS_PREC; | ||
157 | while (loopadd > chop_limit) { | 161 | while (loopadd > chop_limit) { |
158 | lpj += loopadd; | 162 | lpj += loopadd; |
159 | ticks = jiffies; | 163 | ticks = jiffies; |
@@ -165,6 +169,16 @@ static unsigned long __cpuinit calibrate_delay_converge(void) | |||
165 | lpj -= loopadd; | 169 | lpj -= loopadd; |
166 | loopadd >>= 1; | 170 | loopadd >>= 1; |
167 | } | 171 | } |
172 | /* | ||
173 | * If we incremented every single time possible, presume we've | ||
174 | * massively underestimated initially, and retry with a higher | ||
175 | * start, and larger range. (Only seen on x86_64, due to SMIs) | ||
176 | */ | ||
177 | if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) { | ||
178 | lpj_base = lpj; | ||
179 | loopadd_base <<= 2; | ||
180 | goto recalibrate; | ||
181 | } | ||
168 | 182 | ||
169 | return lpj; | 183 | return lpj; |
170 | } | 184 | } |