Skip to content

Commit

Permalink
clocksource, acpi_pm.c: use proper read function also in errata mode
Browse files Browse the repository at this point in the history
On all hardware (some Intel ICH4, PIIX4 and PIIX4E chipsets) affected by a
hardware errata there's about a 4.2% chance that initialization of the
ACPI PMTMR fails.  On those chipsets, we need to read out the timer value
at least three times to get a correct result, for every once in a while
(i.e.  within a 3 ns window every 69.8 ns) the read returns a bogus
result.  During normal operation we work around this issue, but during
initialization reading a bogus value may lead to -EINVAL even though the
hardware is usable.

Thanks to Andreas Mohr for spotting this issue.

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>
  • Loading branch information
Dominik Brodowski authored and Ingo Molnar committed Sep 6, 2008
1 parent 4ff4b9e commit dfdf748
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions drivers/clocksource/acpi_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
*/
static int verify_pmtmr_rate(void)
{
u32 value1, value2;
cycle_t value1, value2;
unsigned long count, delta;

mach_prepare_counter();
value1 = read_pmtmr();
value1 = clocksource_acpi_pm.read();
mach_countup(&count);
value2 = read_pmtmr();
value2 = clocksource_acpi_pm.read();
delta = (value2 - value1) & ACPI_PM_MASK;

/* Check that the PMTMR delta is within 5% of what we expect */
Expand All @@ -177,7 +177,7 @@ static int verify_pmtmr_rate(void)

static int __init init_acpi_pm_clocksource(void)
{
u32 value1, value2;
cycle_t value1, value2;
unsigned int i;

if (!pmtmr_ioport)
Expand All @@ -187,21 +187,21 @@ static int __init init_acpi_pm_clocksource(void)
clocksource_acpi_pm.shift);

/* "verify" this timing source: */
value1 = read_pmtmr();
value1 = clocksource_acpi_pm.read();
for (i = 0; i < 10000; i++) {
value2 = read_pmtmr();
value2 = clocksource_acpi_pm.read();
if (value2 == value1)
continue;
if (value2 > value1)
goto pm_good;
if ((value2 < value1) && ((value2) < 0xFFF))
goto pm_good;
printk(KERN_INFO "PM-Timer had inconsistent results:"
" 0x%#x, 0x%#x - aborting.\n", value1, value2);
" 0x%#llx, 0x%#llx - aborting.\n", value1, value2);
return -EINVAL;
}
printk(KERN_INFO "PM-Timer had no reasonable result:"
" 0x%#x - aborting.\n", value1);
" 0x%#llx - aborting.\n", value1);
return -ENODEV;

pm_good:
Expand Down

0 comments on commit dfdf748

Please sign in to comment.