diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-09-05 17:05:35 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-06 09:33:33 -0400 |
commit | 4ab6a219113197425ac112e35e1ec8062c69888e (patch) | |
tree | dd5458a0dd70c00ef6ba171e7369148905f0b27c | |
parent | dfdf748a61a21b7397b9f57c83de722de71dc56a (diff) |
clocksource, acpi_pm.c: check for monotonicity
The current check for monotonicity is way too weak: Andreas Mohr reports (
http://lkml.org/lkml/2008/8/10/77 ) that on one of his test systems the
current check only triggers in 50% of all cases, leading to catastrophic
timer behaviour. To fix this issue, expand the check for monotonicity by
doing ten consecutive tests instead of one.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | drivers/clocksource/acpi_pm.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 860d033bc74f..4eee533f3f4a 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/delay.h> | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | 26 | ||
26 | /* | 27 | /* |
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void) | |||
175 | #define verify_pmtmr_rate() (0) | 176 | #define verify_pmtmr_rate() (0) |
176 | #endif | 177 | #endif |
177 | 178 | ||
179 | /* Number of monotonicity checks to perform during initialization */ | ||
180 | #define ACPI_PM_MONOTONICITY_CHECKS 10 | ||
181 | |||
178 | static int __init init_acpi_pm_clocksource(void) | 182 | static int __init init_acpi_pm_clocksource(void) |
179 | { | 183 | { |
180 | cycle_t value1, value2; | 184 | cycle_t value1, value2; |
181 | unsigned int i; | 185 | unsigned int i, j, good = 0; |
182 | 186 | ||
183 | if (!pmtmr_ioport) | 187 | if (!pmtmr_ioport) |
184 | return -ENODEV; | 188 | return -ENODEV; |
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void) | |||
187 | clocksource_acpi_pm.shift); | 191 | clocksource_acpi_pm.shift); |
188 | 192 | ||
189 | /* "verify" this timing source: */ | 193 | /* "verify" this timing source: */ |
190 | value1 = clocksource_acpi_pm.read(); | 194 | for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { |
191 | for (i = 0; i < 10000; i++) { | 195 | value1 = clocksource_acpi_pm.read(); |
192 | value2 = clocksource_acpi_pm.read(); | 196 | for (i = 0; i < 10000; i++) { |
193 | if (value2 == value1) | 197 | value2 = clocksource_acpi_pm.read(); |
194 | continue; | 198 | if (value2 == value1) |
195 | if (value2 > value1) | 199 | continue; |
196 | goto pm_good; | 200 | if (value2 > value1) |
197 | if ((value2 < value1) && ((value2) < 0xFFF)) | 201 | good++; |
198 | goto pm_good; | 202 | break; |
199 | printk(KERN_INFO "PM-Timer had inconsistent results:" | 203 | if ((value2 < value1) && ((value2) < 0xFFF)) |
200 | " 0x%#llx, 0x%#llx - aborting.\n", value1, value2); | 204 | good++; |
201 | return -EINVAL; | 205 | break; |
206 | printk(KERN_INFO "PM-Timer had inconsistent results:" | ||
207 | " 0x%#llx, 0x%#llx - aborting.\n", | ||
208 | value1, value2); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | udelay(300 * i); | ||
212 | } | ||
213 | |||
214 | if (good != ACPI_PM_MONOTONICITY_CHECKS) { | ||
215 | printk(KERN_INFO "PM-Timer failed consistency check " | ||
216 | " (0x%#llx) - aborting.\n", value1); | ||
217 | return -ENODEV; | ||
202 | } | 218 | } |
203 | printk(KERN_INFO "PM-Timer had no reasonable result:" | ||
204 | " 0x%#llx - aborting.\n", value1); | ||
205 | return -ENODEV; | ||
206 | 219 | ||
207 | pm_good: | ||
208 | if (verify_pmtmr_rate() != 0) | 220 | if (verify_pmtmr_rate() != 0) |
209 | return -ENODEV; | 221 | return -ENODEV; |
210 | 222 | ||