aboutsummaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/calibrate.c75
1 files changed, 69 insertions, 6 deletions
diff --git a/init/calibrate.c b/init/calibrate.c
index 76ac9194cbc4..cfd7000c9d71 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 )
@@ -90,18 +93,78 @@ 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 printk(KERN_DEBUG "calibrate_delay_direct() timer_rate_max=%lu "
97 "timer_rate_min=%lu pre_start=%lu pre_end=%lu\n",
98 timer_rate_max, timer_rate_min, pre_start, pre_end);
99 if (start >= post_end)
100 printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
101 "timer_rate as we had a TSC wrap around"
102 " start=%lu >=post_end=%lu\n",
103 start, post_end);
104 if (start < post_end && pre_start != 0 && pre_end != 0 &&
94 (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) { 105 (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) {
95 good_timer_count++; 106 good_timer_count++;
96 good_timer_sum += timer_rate_max; 107 good_timer_sum += timer_rate_max;
97 } 108 measured_times[i] = timer_rate_max;
109 if (max < 0 || timer_rate_max > measured_times[max])
110 max = i;
111 if (min < 0 || timer_rate_max < measured_times[min])
112 min = i;
113 } else
114 measured_times[i] = 0;
115
98 } 116 }
99 117
100 if (good_timer_count) 118 /*
101 return (good_timer_sum/good_timer_count); 119 * Find the maximum & minimum - if they differ too much throw out the
120 * one with the largest difference from the mean and try again...
121 */
122 while (good_timer_count > 1) {
123 unsigned long estimate;
124 unsigned long maxdiff;
125
126 /* compute the estimate */
127 estimate = (good_timer_sum/good_timer_count);
128 maxdiff = estimate >> 3;
129
130 /* if range is within 12% let's take it */
131 if ((measured_times[max] - measured_times[min]) < maxdiff)
132 return estimate;
133
134 /* ok - drop the worse value and try again... */
135 good_timer_sum = 0;
136 good_timer_count = 0;
137 if ((measured_times[max] - estimate) <
138 (estimate - measured_times[min])) {
139 printk(KERN_NOTICE "calibrate_delay_direct() dropping "
140 "min bogoMips estimate %d = %lu\n",
141 min, measured_times[min]);
142 measured_times[min] = 0;
143 min = max;
144 } else {
145 printk(KERN_NOTICE "calibrate_delay_direct() dropping "
146 "max bogoMips estimate %d = %lu\n",
147 max, measured_times[max]);
148 measured_times[max] = 0;
149 max = min;
150 }
151
152 for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
153 if (measured_times[i] == 0)
154 continue;
155 good_timer_count++;
156 good_timer_sum += measured_times[i];
157 if (measured_times[i] < measured_times[min])
158 min = i;
159 if (measured_times[i] > measured_times[max])
160 max = i;
161 }
162
163 }
102 164
103 printk(KERN_WARNING "calibrate_delay_direct() failed to get a good " 165 printk(KERN_NOTICE "calibrate_delay_direct() failed to get a good "
104 "estimate for loops_per_jiffy.\nProbably due to long platform interrupts. Consider using \"lpj=\" boot option.\n"); 166 "estimate for loops_per_jiffy.\nProbably due to long platform "
167 "interrupts. Consider using \"lpj=\" boot option.\n");
105 return 0; 168 return 0;
106} 169}
107#else 170#else