···380380 struct clock_event_device *evt, int timer)381381{382382 u32 cnt;383383+ s32 res;383384384385 cnt = hpet_readl(HPET_COUNTER);385386 cnt += (u32) delta;386387 hpet_writel(cnt, HPET_Tn_CMP(timer));387388388389 /*389389- * We need to read back the CMP register on certain HPET390390- * implementations (ATI chipsets) which seem to delay the391391- * transfer of the compare register into the internal compare392392- * logic. With small deltas this might actually be too late as393393- * the counter could already be higher than the compare value394394- * at that point and we would wait for the next hpet interrupt395395- * forever. We found out that reading the CMP register back396396- * forces the transfer so we can rely on the comparison with397397- * the counter register below. If the read back from the398398- * compare register does not match the value we programmed399399- * then we might have a real hardware problem. We can not do400400- * much about it here, but at least alert the user/admin with401401- * a prominent warning.402402- *403403- * An erratum on some chipsets (ICH9,..), results in404404- * comparator read immediately following a write returning old405405- * value. Workaround for this is to read this value second406406- * time, when first read returns old value.407407- *408408- * In fact the write to the comparator register is delayed up409409- * to two HPET cycles so the workaround we tried to restrict410410- * the readback to those known to be borked ATI chipsets411411- * failed miserably. So we give up on optimizations forever412412- * and penalize all HPET incarnations unconditionally.390390+ * HPETs are a complete disaster. The compare register is391391+ * based on a equal comparison and neither provides a less392392+ * than or equal functionality (which would require to take393393+ * the wraparound into account) nor a simple count down event394394+ * mode. Further the write to the comparator register is395395+ * delayed internally up to two HPET clock cycles in certain396396+ * chipsets (ATI, ICH9,10). We worked around that by reading397397+ * back the compare register, but that required another398398+ * workaround for ICH9,10 chips where the first readout after399399+ * write can return the old stale value. We already have a400400+ * minimum delta of 5us enforced, but a NMI or SMI hitting401401+ * between the counter readout and the comparator write can402402+ * move us behind that point easily. Now instead of reading403403+ * the compare register back several times, we make the ETIME404404+ * decision based on the following: Return ETIME if the405405+ * counter value after the write is less than 8 HPET cycles406406+ * away from the event or if the counter is already ahead of407407+ * the event.413408 */414414- if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {415415- if (hpet_readl(HPET_Tn_CMP(timer)) != cnt)416416- printk_once(KERN_WARNING417417- "hpet: compare register read back failed.\n");418418- }409409+ res = (s32)(cnt - hpet_readl(HPET_COUNTER));419410420420- return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;411411+ return res < 8 ? -ETIME : 0;421412}422413423414static void hpet_legacy_set_mode(enum clock_event_mode mode,