aboutsummaryrefslogtreecommitdiffstats
path: root/init/calibrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/calibrate.c')
-rw-r--r--init/calibrate.c192
1 files changed, 143 insertions, 49 deletions
diff --git a/init/calibrate.c b/init/calibrate.c
index 6eb48e53d61c..aae2f40fea4c 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -38,6 +38,9 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
38 unsigned long timer_rate_min, timer_rate_max; 38 unsigned long timer_rate_min, timer_rate_max;
39 unsigned long good_timer_sum = 0; 39 unsigned long good_timer_sum = 0;
40 unsigned long good_timer_count = 0; 40 unsigned long good_timer_count = 0;
41 unsigned long measured_times[MAX_DIRECT_CALIBRATION_RETRIES];
42 int max = -1; /* index of measured_times with max/min values or not set */
43 int min = -1;
41 int i; 44 int i;
42 45
43 if (read_current_timer(&pre_start) < 0 ) 46 if (read_current_timer(&pre_start) < 0 )
@@ -66,7 +69,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
66 pre_start = 0; 69 pre_start = 0;
67 read_current_timer(&start); 70 read_current_timer(&start);
68 start_jiffies = jiffies; 71 start_jiffies = jiffies;
69 while (jiffies <= (start_jiffies + 1)) { 72 while (time_before_eq(jiffies, start_jiffies + 1)) {
70 pre_start = start; 73 pre_start = start;
71 read_current_timer(&start); 74 read_current_timer(&start);
72 } 75 }
@@ -74,8 +77,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
74 77
75 pre_end = 0; 78 pre_end = 0;
76 end = post_start; 79 end = post_start;
77 while (jiffies <= 80 while (time_before_eq(jiffies, start_jiffies + 1 +
78 (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) { 81 DELAY_CALIBRATION_TICKS)) {
79 pre_end = end; 82 pre_end = end;
80 read_current_timer(&end); 83 read_current_timer(&end);
81 } 84 }
@@ -90,18 +93,75 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
90 * If the upper limit and lower limit of the timer_rate is 93 * If the upper limit and lower limit of the timer_rate is
91 * >= 12.5% apart, redo calibration. 94 * >= 12.5% apart, redo calibration.
92 */ 95 */
93 if (pre_start != 0 && pre_end != 0 && 96 if (start >= post_end)
97 printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
98 "timer_rate as we had a TSC wrap around"
99 " start=%lu >=post_end=%lu\n",
100 start, post_end);
101 if (start < post_end && pre_start != 0 && pre_end != 0 &&
94 (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) { 102 (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) {
95 good_timer_count++; 103 good_timer_count++;
96 good_timer_sum += timer_rate_max; 104 good_timer_sum += timer_rate_max;
97 } 105 measured_times[i] = timer_rate_max;
106 if (max < 0 || timer_rate_max > measured_times[max])
107 max = i;
108 if (min < 0 || timer_rate_max < measured_times[min])
109 min = i;
110 } else
111 measured_times[i] = 0;
112
98 } 113 }
99 114
100 if (good_timer_count) 115 /*
101 return (good_timer_sum/good_timer_count); 116 * Find the maximum & minimum - if they differ too much throw out the
117 * one with the largest difference from the mean and try again...
118 */
119 while (good_timer_count > 1) {
120 unsigned long estimate;
121 unsigned long maxdiff;
122
123 /* compute the estimate */
124 estimate = (good_timer_sum/good_timer_count);
125 maxdiff = estimate >> 3;
126
127 /* if range is within 12% let's take it */
128 if ((measured_times[max] - measured_times[min]) < maxdiff)
129 return estimate;
130
131 /* ok - drop the worse value and try again... */
132 good_timer_sum = 0;
133 good_timer_count = 0;
134 if ((measured_times[max] - estimate) <
135 (estimate - measured_times[min])) {
136 printk(KERN_NOTICE "calibrate_delay_direct() dropping "
137 "min bogoMips estimate %d = %lu\n",
138 min, measured_times[min]);
139 measured_times[min] = 0;
140 min = max;
141 } else {
142 printk(KERN_NOTICE "calibrate_delay_direct() dropping "
143 "max bogoMips estimate %d = %lu\n",
144 max, measured_times[max]);
145 measured_times[max] = 0;
146 max = min;
147 }
148
149 for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
150 if (measured_times[i] == 0)
151 continue;
152 good_timer_count++;
153 good_timer_sum += measured_times[i];
154 if (measured_times[i] < measured_times[min])
155 min = i;
156 if (measured_times[i] > measured_times[max])
157 max = i;
158 }
102 159
103 printk(KERN_WARNING "calibrate_delay_direct() failed to get a good " 160 }
104 "estimate for loops_per_jiffy.\nProbably due to long platform interrupts. Consider using \"lpj=\" boot option.\n"); 161
162 printk(KERN_NOTICE "calibrate_delay_direct() failed to get a good "
163 "estimate for loops_per_jiffy.\nProbably due to long platform "
164 "interrupts. Consider using \"lpj=\" boot option.\n");
105 return 0; 165 return 0;
106} 166}
107#else 167#else
@@ -110,8 +170,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
110 170
111/* 171/*
112 * This is the number of bits of precision for the loops_per_jiffy. Each 172 * 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 173 * time we refine our estimate after the first takes 1.5/HZ seconds, so try
114 * better than 1% 174 * to start with a good estimate.
115 * For the boot cpu we can skip the delay calibration and assign it a value 175 * For the boot cpu we can skip the delay calibration and assign it a value
116 * calculated based on the timer frequency. 176 * calculated based on the timer frequency.
117 * For the rest of the CPUs we cannot assume that the timer frequency is same as 177 * For the rest of the CPUs we cannot assume that the timer frequency is same as
@@ -119,64 +179,98 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
119 */ 179 */
120#define LPS_PREC 8 180#define LPS_PREC 8
121 181
182static unsigned long __cpuinit calibrate_delay_converge(void)
183{
184 /* First stage - slowly accelerate to find initial bounds */
185 unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
186 int trials = 0, band = 0, trial_in_band = 0;
187
188 lpj = (1<<12);
189
190 /* wait for "start of" clock tick */
191 ticks = jiffies;
192 while (ticks == jiffies)
193 ; /* nothing */
194 /* Go .. */
195 ticks = jiffies;
196 do {
197 if (++trial_in_band == (1<<band)) {
198 ++band;
199 trial_in_band = 0;
200 }
201 __delay(lpj * band);
202 trials += band;
203 } while (ticks == jiffies);
204 /*
205 * We overshot, so retreat to a clear underestimate. Then estimate
206 * the largest likely undershoot. This defines our chop bounds.
207 */
208 trials -= band;
209 loopadd_base = lpj * band;
210 lpj_base = lpj * trials;
211
212recalibrate:
213 lpj = lpj_base;
214 loopadd = loopadd_base;
215
216 /*
217 * Do a binary approximation to get lpj set to
218 * equal one clock (up to LPS_PREC bits)
219 */
220 chop_limit = lpj >> LPS_PREC;
221 while (loopadd > chop_limit) {
222 lpj += loopadd;
223 ticks = jiffies;
224 while (ticks == jiffies)
225 ; /* nothing */
226 ticks = jiffies;
227 __delay(lpj);
228 if (jiffies != ticks) /* longer than 1 tick */
229 lpj -= loopadd;
230 loopadd >>= 1;
231 }
232 /*
233 * If we incremented every single time possible, presume we've
234 * massively underestimated initially, and retry with a higher
235 * start, and larger range. (Only seen on x86_64, due to SMIs)
236 */
237 if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
238 lpj_base = lpj;
239 loopadd_base <<= 2;
240 goto recalibrate;
241 }
242
243 return lpj;
244}
245
122void __cpuinit calibrate_delay(void) 246void __cpuinit calibrate_delay(void)
123{ 247{
124 unsigned long ticks, loopbit; 248 unsigned long lpj;
125 int lps_precision = LPS_PREC;
126 static bool printed; 249 static bool printed;
127 250
128 if (preset_lpj) { 251 if (preset_lpj) {
129 loops_per_jiffy = preset_lpj; 252 lpj = preset_lpj;
130 if (!printed) 253 if (!printed)
131 pr_info("Calibrating delay loop (skipped) " 254 pr_info("Calibrating delay loop (skipped) "
132 "preset value.. "); 255 "preset value.. ");
133 } else if ((!printed) && lpj_fine) { 256 } else if ((!printed) && lpj_fine) {
134 loops_per_jiffy = lpj_fine; 257 lpj = lpj_fine;
135 pr_info("Calibrating delay loop (skipped), " 258 pr_info("Calibrating delay loop (skipped), "
136 "value calculated using timer frequency.. "); 259 "value calculated using timer frequency.. ");
137 } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) { 260 } else if ((lpj = calibrate_delay_direct()) != 0) {
138 if (!printed) 261 if (!printed)
139 pr_info("Calibrating delay using timer " 262 pr_info("Calibrating delay using timer "
140 "specific routine.. "); 263 "specific routine.. ");
141 } else { 264 } else {
142 loops_per_jiffy = (1<<12);
143
144 if (!printed) 265 if (!printed)
145 pr_info("Calibrating delay loop... "); 266 pr_info("Calibrating delay loop... ");
146 while ((loops_per_jiffy <<= 1) != 0) { 267 lpj = 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 } 268 }
176 if (!printed) 269 if (!printed)
177 pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", 270 pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
178 loops_per_jiffy/(500000/HZ), 271 lpj/(500000/HZ),
179 (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); 272 (lpj/(5000/HZ)) % 100, lpj);
180 273
274 loops_per_jiffy = lpj;
181 printed = true; 275 printed = true;
182} 276}