[Top][All Lists]
[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 */
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] Rework the RTL8139C timer interrupts and enable them by default,
Tim Deegan <=