diff options
Diffstat (limited to 'init/calibrate.c')
-rw-r--r-- | init/calibrate.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/init/calibrate.c b/init/calibrate.c index 24fe022c55f9..76ac9194cbc4 100644 --- a/init/calibrate.c +++ b/init/calibrate.c | |||
@@ -110,8 +110,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} | |||
110 | 110 | ||
111 | /* | 111 | /* |
112 | * This is the number of bits of precision for the loops_per_jiffy. Each | 112 | * This is the number of bits of precision for the loops_per_jiffy. Each |
113 | * bit takes on average 1.5/HZ seconds. This (like the original) is a little | 113 | * time we refine our estimate after the first takes 1.5/HZ seconds, so try |
114 | * better than 1% | 114 | * to start with a good estimate. |
115 | * For the boot cpu we can skip the delay calibration and assign it a value | 115 | * For the boot cpu we can skip the delay calibration and assign it a value |
116 | * calculated based on the timer frequency. | 116 | * calculated based on the timer frequency. |
117 | * For the rest of the CPUs we cannot assume that the timer frequency is same as | 117 | * For the rest of the CPUs we cannot assume that the timer frequency is same as |
@@ -119,10 +119,72 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} | |||
119 | */ | 119 | */ |
120 | #define LPS_PREC 8 | 120 | #define LPS_PREC 8 |
121 | 121 | ||
122 | static unsigned long __cpuinit calibrate_delay_converge(void) | ||
123 | { | ||
124 | /* First stage - slowly accelerate to find initial bounds */ | ||
125 | unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit; | ||
126 | int trials = 0, band = 0, trial_in_band = 0; | ||
127 | |||
128 | lpj = (1<<12); | ||
129 | |||
130 | /* wait for "start of" clock tick */ | ||
131 | ticks = jiffies; | ||
132 | while (ticks == jiffies) | ||
133 | ; /* nothing */ | ||
134 | /* Go .. */ | ||
135 | ticks = jiffies; | ||
136 | do { | ||
137 | if (++trial_in_band == (1<<band)) { | ||
138 | ++band; | ||
139 | trial_in_band = 0; | ||
140 | } | ||
141 | __delay(lpj * band); | ||
142 | trials += band; | ||
143 | } while (ticks == jiffies); | ||
144 | /* | ||
145 | * We overshot, so retreat to a clear underestimate. Then estimate | ||
146 | * the largest likely undershoot. This defines our chop bounds. | ||
147 | */ | ||
148 | trials -= band; | ||
149 | loopadd_base = lpj * band; | ||
150 | lpj_base = lpj * trials; | ||
151 | |||
152 | recalibrate: | ||
153 | lpj = lpj_base; | ||
154 | loopadd = loopadd_base; | ||
155 | |||
156 | /* | ||
157 | * Do a binary approximation to get lpj set to | ||
158 | * equal one clock (up to LPS_PREC bits) | ||
159 | */ | ||
160 | chop_limit = lpj >> LPS_PREC; | ||
161 | while (loopadd > chop_limit) { | ||
162 | lpj += loopadd; | ||
163 | ticks = jiffies; | ||
164 | while (ticks == jiffies) | ||
165 | ; /* nothing */ | ||
166 | ticks = jiffies; | ||
167 | __delay(lpj); | ||
168 | if (jiffies != ticks) /* longer than 1 tick */ | ||
169 | lpj -= loopadd; | ||
170 | loopadd >>= 1; | ||
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 | } | ||
182 | |||
183 | return lpj; | ||
184 | } | ||
185 | |||
122 | void __cpuinit calibrate_delay(void) | 186 | void __cpuinit calibrate_delay(void) |
123 | { | 187 | { |
124 | unsigned long ticks, loopbit; | ||
125 | int lps_precision = LPS_PREC; | ||
126 | static bool printed; | 188 | static bool printed; |
127 | 189 | ||
128 | if (preset_lpj) { | 190 | if (preset_lpj) { |
@@ -139,39 +201,9 @@ void __cpuinit calibrate_delay(void) | |||
139 | pr_info("Calibrating delay using timer " | 201 | pr_info("Calibrating delay using timer " |
140 | "specific routine.. "); | 202 | "specific routine.. "); |
141 | } else { | 203 | } else { |
142 | loops_per_jiffy = (1<<12); | ||
143 | |||
144 | if (!printed) | 204 | if (!printed) |
145 | pr_info("Calibrating delay loop... "); | 205 | pr_info("Calibrating delay loop... "); |
146 | while ((loops_per_jiffy <<= 1) != 0) { | 206 | loops_per_jiffy = calibrate_delay_converge(); |
147 | /* wait for "start of" clock tick */ | ||
148 | ticks = jiffies; | ||
149 | while (ticks == jiffies) | ||
150 | /* nothing */; | ||
151 | /* Go .. */ | ||
152 | ticks = jiffies; | ||
153 | __delay(loops_per_jiffy); | ||
154 | ticks = jiffies - ticks; | ||
155 | if (ticks) | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Do a binary approximation to get loops_per_jiffy set to | ||
161 | * equal one clock (up to lps_precision bits) | ||
162 | */ | ||
163 | loops_per_jiffy >>= 1; | ||
164 | loopbit = loops_per_jiffy; | ||
165 | while (lps_precision-- && (loopbit >>= 1)) { | ||
166 | loops_per_jiffy |= loopbit; | ||
167 | ticks = jiffies; | ||
168 | while (ticks == jiffies) | ||
169 | /* nothing */; | ||
170 | ticks = jiffies; | ||
171 | __delay(loops_per_jiffy); | ||
172 | if (jiffies != ticks) /* longer than 1 tick */ | ||
173 | loops_per_jiffy &= ~loopbit; | ||
174 | } | ||
175 | } | 207 | } |
176 | if (!printed) | 208 | if (!printed) |
177 | pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", | 209 | pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", |