[xen-unstable] Improve HPET comparator reprog to prevent intr-near-missing case

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[xen-unstable] Improve HPET comparator reprog to prevent intr-near-missing case

Xen patchbot-unstable
# HG changeset patch
# User Keir Fraser <[hidden email]>
# Date 1212482479 -3600
# Node ID 5603534c62f922b0106f2291100fbf135d69d072
# Parent  6b77c311fd3c90db5a0cbbcfc44bf8d99b709b2b
Improve HPET comparator reprog to prevent intr-near-missing case

HPET intr-near-missing means if the current counter value is too close
to the comparator value to be reprogrammed the expected HPET intr may
be missing. Linux kernel uses a mininal 48-hpet-ticks(~3.5us) distance
to workaround this, but personal observation showed there is still
failure case while delta=3D0xba (~13.5us). So choosing 20us as the
MIN_DELTA_NS should be helpful to prevent near-missing from happening.

local_irq_save/restore were used to avoid disturbance. (+ 2) was used
as a final guard to avoid wrong judgement due to the real happened
near-missing case.

Signed-off-by: Wei Gang <[hidden email]>
Signed-off-by: Tian Kevin <[hidden email]>
---
 xen/arch/x86/hpet.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff -r 6b77c311fd3c -r 5603534c62f9 xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c Tue Jun 03 09:35:02 2008 +0100
+++ b/xen/arch/x86/hpet.c Tue Jun 03 09:41:19 2008 +0100
@@ -17,7 +17,7 @@
 #define STIME_MAX ((s_time_t)((uint64_t)~0ull>>1))
 
 #define MAX_DELTA_NS MILLISECS(10*1000)
-#define MIN_DELTA_NS MICROSECS(1)
+#define MIN_DELTA_NS MICROSECS(20)
 
 struct hpet_event_channel
 {
@@ -67,13 +67,18 @@ static inline unsigned long ns2ticks(uns
 
 static int hpet_legacy_next_event(unsigned long delta)
 {
-    unsigned long cnt;
-
+    uint32_t cnt, cmp;
+    unsigned long flags;
+
+    local_irq_save(flags);
     cnt = hpet_read32(HPET_COUNTER);
-    cnt += delta;
-    hpet_write32(cnt, HPET_T0_CMP);
-
-    return ((long)(hpet_read32(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
+    cmp = cnt + delta;
+    hpet_write32(cmp, HPET_T0_CMP);
+    cmp = hpet_read32(HPET_COUNTER);
+    local_irq_restore(flags);
+
+    /* Are we within two ticks of the deadline passing? Then we may miss. */
+    return ((cmp + 2 - cnt) > delta) ? -ETIME : 0;
 }
 
 static int reprogram_hpet_evt_channel(

_______________________________________________
Xen-changelog mailing list
[hidden email]
http://lists.xensource.com/xen-changelog