|
@@ -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;
|