aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2008-09-05 17:05:35 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-06 09:33:33 -0400
commit4ab6a219113197425ac112e35e1ec8062c69888e (patch)
treedd5458a0dd70c00ef6ba171e7369148905f0b27c
parentdfdf748a61a21b7397b9f57c83de722de71dc56a (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.c46
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
178static int __init init_acpi_pm_clocksource(void) 182static 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
207pm_good:
208 if (verify_pmtmr_rate() != 0) 220 if (verify_pmtmr_rate() != 0)
209 return -ENODEV; 221 return -ENODEV;
210 222