Merge commit 'v2.6.35' into kbuild/kbuild
[deliverable/linux.git] / arch / x86 / kernel / hpet.c
index 23b4ecdffa9bcc76dc0659ab6e6ed1c7882ad677..ba390d731175a492686643dd873786eafda9521b 100644 (file)
@@ -36,6 +36,7 @@
 unsigned long                          hpet_address;
 u8                                     hpet_blockid; /* OS timer block num */
 u8                                     hpet_msi_disable;
+u8                                     hpet_readback_cmp;
 
 #ifdef CONFIG_PCI_MSI
 static unsigned long                   hpet_num_timers;
@@ -395,19 +396,23 @@ static int hpet_next_event(unsigned long delta,
         * at that point and we would wait for the next hpet interrupt
         * forever. We found out that reading the CMP register back
         * forces the transfer so we can rely on the comparison with
-        * the counter register below. If the read back from the
-        * compare register does not match the value we programmed
-        * then we might have a real hardware problem. We can not do
-        * much about it here, but at least alert the user/admin with
-        * a prominent warning.
-        * An erratum on some chipsets (ICH9,..), results in comparator read
-        * immediately following a write returning old value. Workaround
-        * for this is to read this value second time, when first
-        * read returns old value.
+        * the counter register below.
+        *
+        * That works fine on those ATI chipsets, but on newer Intel
+        * chipsets (ICH9...) this triggers due to an erratum: Reading
+        * the comparator immediately following a write is returning
+        * the old value.
+        *
+        * We restrict the read back to the affected ATI chipsets (set
+        * by quirks) and also run it with hpet=verbose for debugging
+        * purposes.
         */
-       if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {
-               WARN_ONCE(hpet_readl(HPET_Tn_CMP(timer)) != cnt,
-                 KERN_WARNING "hpet: compare register read back failed.\n");
+       if (hpet_readback_cmp || hpet_verbose) {
+               u32 cmp = hpet_readl(HPET_Tn_CMP(timer));
+
+               if (cmp != cnt)
+                       printk_once(KERN_WARNING
+                           "hpet: compare register read back failed.\n");
        }
 
        return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
@@ -959,7 +964,7 @@ fs_initcall(hpet_late_init);
 
 void hpet_disable(void)
 {
-       if (is_hpet_capable()) {
+       if (is_hpet_capable() && hpet_virt_address) {
                unsigned int cfg = hpet_readl(HPET_CFG);
 
                if (hpet_legacy_int_enabled) {
This page took 0.030734 seconds and 5 git commands to generate.