Skip to content

Commit 4ab6a21

Browse files
Dominik BrodowskiIngo Molnar
authored andcommitted
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 <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent dfdf748 commit 4ab6a21

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

drivers/clocksource/acpi_pm.c

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/errno.h>
2222
#include <linux/init.h>
2323
#include <linux/pci.h>
24+
#include <linux/delay.h>
2425
#include <asm/io.h>
2526

2627
/*
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
175176
#define verify_pmtmr_rate() (0)
176177
#endif
177178

179+
/* Number of monotonicity checks to perform during initialization */
180+
#define ACPI_PM_MONOTONICITY_CHECKS 10
181+
178182
static int __init init_acpi_pm_clocksource(void)
179183
{
180184
cycle_t value1, value2;
181-
unsigned int i;
185+
unsigned int i, j, good = 0;
182186

183187
if (!pmtmr_ioport)
184188
return -ENODEV;
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
187191
clocksource_acpi_pm.shift);
188192

189193
/* "verify" this timing source: */
190-
value1 = clocksource_acpi_pm.read();
191-
for (i = 0; i < 10000; i++) {
192-
value2 = clocksource_acpi_pm.read();
193-
if (value2 == value1)
194-
continue;
195-
if (value2 > value1)
196-
goto pm_good;
197-
if ((value2 < value1) && ((value2) < 0xFFF))
198-
goto pm_good;
199-
printk(KERN_INFO "PM-Timer had inconsistent results:"
200-
" 0x%#llx, 0x%#llx - aborting.\n", value1, value2);
201-
return -EINVAL;
194+
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
195+
value1 = clocksource_acpi_pm.read();
196+
for (i = 0; i < 10000; i++) {
197+
value2 = clocksource_acpi_pm.read();
198+
if (value2 == value1)
199+
continue;
200+
if (value2 > value1)
201+
good++;
202+
break;
203+
if ((value2 < value1) && ((value2) < 0xFFF))
204+
good++;
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;
202218
}
203-
printk(KERN_INFO "PM-Timer had no reasonable result:"
204-
" 0x%#llx - aborting.\n", value1);
205-
return -ENODEV;
206219

207-
pm_good:
208220
if (verify_pmtmr_rate() != 0)
209221
return -ENODEV;
210222

0 commit comments

Comments
 (0)