qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] uhci: Lower uhci timer freq when guest is idle


From: arei.gonglei
Subject: [Qemu-devel] [PATCH] uhci: Lower uhci timer freq when guest is idle
Date: Wed, 26 Mar 2014 11:57:23 +0800

From: Gonglei <address@hidden>

UHCI emulation polls the device at a freq of 1000HZ, which consumes
12~13% CPU even though a Windows guest is completely idle when the guest
was configed usb1.1 tablet devcie. This solution counts accumulated NAK
packets. when it reaches to 64, then the guest is supposed to be idle
and the freq is lowered to 10HZ.

This patch has been tested on Win7/WinXP/Win2008 guests, that reduces
the CPU consume from 12~13% to 6~7%.

Signed-off-by: Gonglei <address@hidden>
---
 hw/usb/hcd-uhci.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 0820244..fb86959 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -73,6 +73,7 @@
 #define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
 
 #define FRAME_TIMER_FREQ 1000
+#define PERIODIC_INACTIVE  64
 
 #define FRAME_MAX_LOOPS  256
 
@@ -173,6 +174,8 @@ struct UHCIState {
     char *masterbus;
     uint32_t firstport;
     uint32_t maxframes;
+
+    /* Accumulated NAK counter */
+    uint32_t async_naks;
 };
 
 typedef struct UHCI_TD {
@@ -920,6 +923,12 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, 
uint32_t qh_addr,
         uhci_update_irq(s);
         return TD_RESULT_STOP_FRAME;
     }
+
+    if (async->packet.status == USB_RET_NAK) {
+        s->async_naks++;
+    } else {
+        s->async_naks = 0;
+    }
 
     if (async->packet.status == USB_RET_ASYNC) {
         uhci_async_link(async);
@@ -1153,6 +1162,7 @@ static void uhci_frame_timer(void *opaque)
 {
     UHCIState *s = opaque;
     uint64_t t_now, t_last_run;
+    uint64_t t_now, t_last_run, t_next;
     int i, frames;
     const uint64_t frame_t = get_ticks_per_sec() / FRAME_TIMER_FREQ;
 
@@ -1205,7 +1215,12 @@ static void uhci_frame_timer(void *opaque)
     }
     s->pending_int_mask = 0;
 
-    timer_mod(s->frame_timer, t_now + frame_t);
+    t_next = t_now + frame_t;
+    /* slower down the timer if the guest vm is idle */
+    if (s->async_naks > PERIODIC_INACTIVE) {
+        t_next += 100 * frame_t;
+    }
+
+    timer_mod(s->frame_timer, t_next);
 }
 
 static const MemoryRegionOps uhci_ioport_ops = {
-- 
1.6.0.2





reply via email to

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