diff options
Diffstat (limited to 'drivers/clocksource/acpi_pm.c')
| -rw-r--r-- | drivers/clocksource/acpi_pm.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 5ca1d80de182..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 | /* |
| @@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, | |||
| 151 | */ | 152 | */ |
| 152 | static int verify_pmtmr_rate(void) | 153 | static int verify_pmtmr_rate(void) |
| 153 | { | 154 | { |
| 154 | u32 value1, value2; | 155 | cycle_t value1, value2; |
| 155 | unsigned long count, delta; | 156 | unsigned long count, delta; |
| 156 | 157 | ||
| 157 | mach_prepare_counter(); | 158 | mach_prepare_counter(); |
| 158 | value1 = read_pmtmr(); | 159 | value1 = clocksource_acpi_pm.read(); |
| 159 | mach_countup(&count); | 160 | mach_countup(&count); |
| 160 | value2 = read_pmtmr(); | 161 | value2 = clocksource_acpi_pm.read(); |
| 161 | delta = (value2 - value1) & ACPI_PM_MASK; | 162 | delta = (value2 - value1) & ACPI_PM_MASK; |
| 162 | 163 | ||
| 163 | /* Check that the PMTMR delta is within 5% of what we expect */ | 164 | /* Check that the PMTMR delta is within 5% of what we expect */ |
| @@ -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 | |||
| 178 | static int __init init_acpi_pm_clocksource(void) | 182 | static int __init init_acpi_pm_clocksource(void) |
| 179 | { | 183 | { |
| 180 | u32 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 = read_pmtmr(); | 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 = read_pmtmr(); | 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%#x, 0x%#x - 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%#x - aborting.\n", value1); | ||
| 205 | return -ENODEV; | ||
| 206 | 219 | ||
| 207 | pm_good: | ||
| 208 | if (verify_pmtmr_rate() != 0) | 220 | if (verify_pmtmr_rate() != 0) |
| 209 | return -ENODEV; | 221 | return -ENODEV; |
| 210 | 222 | ||
