diff options
| author | john stultz <johnstul@us.ibm.com> | 2006-12-08 05:36:02 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:37 -0500 |
| commit | 562f9c574e0707f9159a729ea41faf53b221cd30 (patch) | |
| tree | 54fb7d5195d09cd7ce9ceb312a98d7538e8a34f0 /drivers/clocksource | |
| parent | a2ee8649ba6d71416712e798276bf7c40b64e6e5 (diff) | |
[PATCH] time: re-add verify_pmtmr_rate
This patch re-adds the verify_pmtmr_rate functionality from 2.6.17 that
I dropped 2.6.18.
This resolves problems seen on older K6 ASUS boards where the ACPI PM
timer runs too fast.
See:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=211902
http://bugme.osdl.org/show_bug.cgi?id=2375
Thanks to Ian Campbell for re-reporting this and testing the fix!
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Ian Campbell <ijc@hellion.org.uk>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/clocksource')
| -rw-r--r-- | drivers/clocksource/acpi_pm.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 7fcb77a9d011..8ab61ef97b4c 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c | |||
| @@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, | |||
| 142 | acpi_pm_check_graylist); | 142 | acpi_pm_check_graylist); |
| 143 | #endif | 143 | #endif |
| 144 | 144 | ||
| 145 | #ifndef CONFIG_X86_64 | ||
| 146 | #include "mach_timer.h" | ||
| 147 | #define PMTMR_EXPECTED_RATE \ | ||
| 148 | ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) | ||
| 149 | /* | ||
| 150 | * Some boards have the PMTMR running way too fast. We check | ||
| 151 | * the PMTMR rate against PIT channel 2 to catch these cases. | ||
| 152 | */ | ||
| 153 | static int verify_pmtmr_rate(void) | ||
| 154 | { | ||
| 155 | u32 value1, value2; | ||
| 156 | unsigned long count, delta; | ||
| 157 | |||
| 158 | mach_prepare_counter(); | ||
| 159 | value1 = read_pmtmr(); | ||
| 160 | mach_countup(&count); | ||
| 161 | value2 = read_pmtmr(); | ||
| 162 | delta = (value2 - value1) & ACPI_PM_MASK; | ||
| 163 | |||
| 164 | /* Check that the PMTMR delta is within 5% of what we expect */ | ||
| 165 | if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || | ||
| 166 | delta > (PMTMR_EXPECTED_RATE * 21) / 20) { | ||
| 167 | printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% " | ||
| 168 | "of normal - aborting.\n", | ||
| 169 | 100UL * delta / PMTMR_EXPECTED_RATE); | ||
| 170 | return -1; | ||
| 171 | } | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | #else | ||
| 176 | #define verify_pmtmr_rate() (0) | ||
| 177 | #endif | ||
| 145 | 178 | ||
| 146 | static int __init init_acpi_pm_clocksource(void) | 179 | static int __init init_acpi_pm_clocksource(void) |
| 147 | { | 180 | { |
| @@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void) | |||
| 173 | return -ENODEV; | 206 | return -ENODEV; |
| 174 | 207 | ||
| 175 | pm_good: | 208 | pm_good: |
| 209 | if (verify_pmtmr_rate() != 0) | ||
| 210 | return -ENODEV; | ||
| 211 | |||
| 176 | return clocksource_register(&clocksource_acpi_pm); | 212 | return clocksource_register(&clocksource_acpi_pm); |
| 177 | } | 213 | } |
| 178 | 214 | ||
