qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Rework the RTL8139C timer interrupts and enable the


From: Tim Deegan
Subject: [Qemu-devel] [PATCH] Rework the RTL8139C timer interrupts and enable them by default
Date: Mon, 15 Dec 2008 15:42:58 +0000
User-agent: Mutt/1.5.17 (2007-11-01)

Reorganise the RTL8139 rolling timer so that it calculates the counter
on read instead of updating it in real time, and only sets a timer when
the guest has programmed a timer interrupt.

Enable it by default since it should have no overhead for guests that
don't use it, and OpenBSD's rtl8139 driver relies on it.

Signed-off-by: Tim Deegan <address@hidden>
---
 rtl8139.c |   87 ++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 43 insertions(+), 44 deletions(-)

Index: hw/rtl8139.c
===================================================================
--- hw/rtl8139.c        (revision 6042)
+++ hw/rtl8139.c        (working copy)
@@ -59,8 +59,8 @@
 /* Calculate CRCs properly on Rx packets */
 #define RTL8139_CALCULATE_RXCRC 1
 
-/* Uncomment to enable on-board timer interrupts */
-//#define RTL8139_ONBOARD_TIMER 1
+/* Enable on-board timer interrupts */
+#define RTL8139_ONBOARD_TIMER 1
 
 #if defined(RTL8139_CALCULATE_RXCRC)
 /* For crc32 */
@@ -497,6 +497,37 @@
 
 } RTL8139State;
 
+/* Fix up the TCTR field to match the current system time */
+static inline void rtl8139_update_tctr(RTL8139State *s, int64_t current_time)
+{
+    if (s->clock_enabled)
+        s->TCTR = muldiv64(current_time - s->TCTR_base, PCI_FREQUENCY, 
ticks_per_sec);
+}
+
+/* Queue a timer interrupt based on the state of the TCTR and TimerInt */
+static inline void rtl8139_set_tctr_timer(RTL8139State *s)
+{
+#if RTL8139_ONBOARD_TIMER
+    int64_t next_time;
+    int64_t curr_time = qemu_get_clock(vm_clock);
+
+    if (!s->clock_enabled || s->TimerInt == 0) 
+    {
+        DEBUG_PRINT(("RTL8139: >>> set timer: clock not running or timeout not 
set\n"));
+        return;
+    }
+
+    rtl8139_update_tctr(s, curr_time);
+    next_time = curr_time +
+        muldiv64((1 + s->TimerInt - s->TCTR), ticks_per_sec, PCI_FREQUENCY);
+
+    if (next_time <= curr_time)
+        next_time = curr_time + 1;
+
+    qemu_mod_timer(s->timer, next_time);
+#endif
+}
+
 static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
 {
     DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
@@ -2788,11 +2819,13 @@
             DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
             s->TCTR = 0;
             s->TCTR_base = qemu_get_clock(vm_clock);
+            rtl8139_set_tctr_timer(s);
             break;
 
         case FlashReg:
             DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", 
val));
             s->TimerInt = val;
+            rtl8139_set_tctr_timer(s);
             break;
 
         default:
@@ -3002,6 +3035,7 @@
             break;
 
         case Timer:
+            rtl8139_update_tctr(s, qemu_get_clock(vm_clock));
             ret = s->TCTR;
             DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
             break;
@@ -3287,6 +3321,7 @@
         qemu_get_be32s(f, &s->TimerInt);
         s->TCTR_base=qemu_get_be64(f);
 
+        rtl8139_set_tctr_timer(s);
         RTL8139TallyCounters_load(f, &s->tally_counters);
     }
     else
@@ -3347,56 +3382,23 @@
     rtl8139_mmio_writel,
 };
 
-static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t 
current_time)
-{
-    int64_t next_time = current_time +
-        muldiv64(1, ticks_per_sec, PCI_FREQUENCY);
-    if (next_time <= current_time)
-        next_time = current_time + 1;
-    return next_time;
-}
-
 #ifdef RTL8139_ONBOARD_TIMER
 static void rtl8139_timer(void *opaque)
 {
     RTL8139State *s = opaque;
 
-    int is_timeout = 0;
-
-    int64_t  curr_time;
-    uint32_t curr_tick;
-
-    if (!s->clock_enabled)
+    if (!s->clock_enabled || s->TimerInt == 0)
     {
-        DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n"));
+        DEBUG_PRINT(("RTL8139: >>> timer: clock not running or timeout not 
set\n"));
         return;
     }
 
-    curr_time = qemu_get_clock(vm_clock);
+    s->IntrStatus |= PCSTimeout;
+    rtl8139_update_irq(s);
 
-    curr_tick = muldiv64(curr_time - s->TCTR_base, PCI_FREQUENCY, 
ticks_per_sec);
+    rtl8139_set_tctr_timer(s);
 
-    if (s->TimerInt && curr_tick >= s->TimerInt)
-    {
-        if (s->TCTR < s->TimerInt || curr_tick < s->TCTR)
-        {
-            is_timeout = 1;
-        }
-    }
-
-    s->TCTR = curr_tick;
-
-//  DEBUG_PRINT(("RTL8139: >>> timer: tick=%08u\n", s->TCTR));
-
-    if (is_timeout)
-    {
-        DEBUG_PRINT(("RTL8139: >>> timer: timeout tick=%08u\n", s->TCTR));
-        s->IntrStatus |= PCSTimeout;
-        rtl8139_update_irq(s);
-    }
-
-    qemu_mod_timer(s->timer,
-        rtl8139_get_next_tctr_time(s,curr_time));
+    DEBUG_PRINT(("RTL8139: >>> timer: timeout tick=%08u (%08u)\n", s->TCTR, 
s->TimerInt));
 }
 #endif /* RTL8139_ONBOARD_TIMER */
 
@@ -3458,8 +3460,5 @@
 
 #ifdef RTL8139_ONBOARD_TIMER
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
-
-    qemu_mod_timer(s->timer,
-        rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
 #endif /* RTL8139_ONBOARD_TIMER */
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]