mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
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>
This commit is contained in:
parent
dfdf748a61
commit
4ab6a21911
1 changed files with 29 additions and 17 deletions
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
|
||||||
#define verify_pmtmr_rate() (0)
|
#define verify_pmtmr_rate() (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Number of monotonicity checks to perform during initialization */
|
||||||
|
#define ACPI_PM_MONOTONICITY_CHECKS 10
|
||||||
|
|
||||||
static int __init init_acpi_pm_clocksource(void)
|
static int __init init_acpi_pm_clocksource(void)
|
||||||
{
|
{
|
||||||
cycle_t value1, value2;
|
cycle_t value1, value2;
|
||||||
unsigned int i;
|
unsigned int i, j, good = 0;
|
||||||
|
|
||||||
if (!pmtmr_ioport)
|
if (!pmtmr_ioport)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
|
||||||
clocksource_acpi_pm.shift);
|
clocksource_acpi_pm.shift);
|
||||||
|
|
||||||
/* "verify" this timing source: */
|
/* "verify" this timing source: */
|
||||||
|
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
|
||||||
value1 = clocksource_acpi_pm.read();
|
value1 = clocksource_acpi_pm.read();
|
||||||
for (i = 0; i < 10000; i++) {
|
for (i = 0; i < 10000; i++) {
|
||||||
value2 = clocksource_acpi_pm.read();
|
value2 = clocksource_acpi_pm.read();
|
||||||
if (value2 == value1)
|
if (value2 == value1)
|
||||||
continue;
|
continue;
|
||||||
if (value2 > value1)
|
if (value2 > value1)
|
||||||
goto pm_good;
|
good++;
|
||||||
|
break;
|
||||||
if ((value2 < value1) && ((value2) < 0xFFF))
|
if ((value2 < value1) && ((value2) < 0xFFF))
|
||||||
goto pm_good;
|
good++;
|
||||||
|
break;
|
||||||
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
||||||
" 0x%#llx, 0x%#llx - aborting.\n", value1, value2);
|
" 0x%#llx, 0x%#llx - aborting.\n",
|
||||||
|
value1, value2);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "PM-Timer had no reasonable result:"
|
udelay(300 * i);
|
||||||
" 0x%#llx - aborting.\n", value1);
|
}
|
||||||
return -ENODEV;
|
|
||||||
|
if (good != ACPI_PM_MONOTONICITY_CHECKS) {
|
||||||
|
printk(KERN_INFO "PM-Timer failed consistency check "
|
||||||
|
" (0x%#llx) - aborting.\n", value1);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
pm_good:
|
|
||||||
if (verify_pmtmr_rate() != 0)
|
if (verify_pmtmr_rate() != 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue