From patchwork Wed Mar 26 03:57:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gonglei (Arei)" X-Patchwork-Id: 333774 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E6EED1400A6 for ; Wed, 26 Mar 2014 14:58:57 +1100 (EST) Received: from localhost ([::1]:45425 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSezO-0007Sn-J2 for incoming@patchwork.ozlabs.org; Tue, 25 Mar 2014 23:58:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41720) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSez6-0007SL-0i for qemu-devel@nongnu.org; Tue, 25 Mar 2014 23:58:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WSez0-0006Qn-Uz for qemu-devel@nongnu.org; Tue, 25 Mar 2014 23:58:35 -0400 Received: from szxga01-in.huawei.com ([119.145.14.64]:37663) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSez0-0006Pc-BO for qemu-devel@nongnu.org; Tue, 25 Mar 2014 23:58:30 -0400 Received: from 172.24.2.119 (EHLO szxeml209-edg.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id BTE40388; Wed, 26 Mar 2014 11:58:08 +0800 (CST) Received: from SZXEML456-HUB.china.huawei.com (10.82.67.199) by szxeml209-edg.china.huawei.com (172.24.2.184) with Microsoft SMTP Server (TLS) id 14.3.158.1; Wed, 26 Mar 2014 11:57:41 +0800 Received: from localhost (10.177.19.102) by szxeml456-hub.china.huawei.com (10.82.67.199) with Microsoft SMTP Server id 14.3.158.1; Wed, 26 Mar 2014 11:57:34 +0800 From: To: Date: Wed, 26 Mar 2014 11:57:23 +0800 Message-ID: <1395806243-11316-1-git-send-email-arei.gonglei@huawei.com> X-Mailer: git-send-email 1.7.3.1.msysgit.0 MIME-Version: 1.0 X-Originating-IP: [10.177.19.102] X-CFilter-Loop: Reflected X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 119.145.14.64 Cc: Gonglei , weidong.huang@huawei.com, kraxel@redhat.com Subject: [Qemu-devel] [PATCH] uhci: Lower uhci timer freq when guest is idle X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Gonglei 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 --- 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 = {