From patchwork Wed Nov 21 13:59:58 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 200777 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 5DA2F2C0093 for ; Thu, 22 Nov 2012 01:26:22 +1100 (EST) Received: from localhost ([::1]:41633 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBFs-0005c1-6h for incoming@patchwork.ozlabs.org; Wed, 21 Nov 2012 09:26:20 -0500 Received: from eggs.gnu.org ([208.118.235.92]:54104) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBFh-0005ay-D9 for qemu-devel@nongnu.org; Wed, 21 Nov 2012 09:26:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TbBFb-0003pl-7K for qemu-devel@nongnu.org; Wed, 21 Nov 2012 09:26:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:64438) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBFa-0003pe-UJ for qemu-devel@nongnu.org; Wed, 21 Nov 2012 09:26:03 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qALEQ1mQ027504 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 21 Nov 2012 09:26:02 -0500 Received: from rincewind.home.kraxel.org (ovpn-116-26.ams2.redhat.com [10.36.116.26]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qALE06O4018731; Wed, 21 Nov 2012 09:00:07 -0500 Received: by rincewind.home.kraxel.org (Postfix, from userid 500) id 26CE440AEA; Wed, 21 Nov 2012 15:00:05 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Wed, 21 Nov 2012 14:59:58 +0100 Message-Id: <1353506404-29446-2-git-send-email-kraxel@redhat.com> In-Reply-To: <1353506404-29446-1-git-send-email-kraxel@redhat.com> References: <1353506404-29446-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Hans de Goede , Gerd Hoffmann Subject: [Qemu-devel] [PATCH 1/7] uhci: Add a completions_only flag for async completions 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: Hans de Goede Add a completions_only flag, and set this when running process_frame for async completion handling, this fixes 2 issues in a single patch: 1) It makes sure async completed packets get written to guest mem immediately, even if all the bandwidth for the frame was consumed from the timer run process_frame. This is necessary as delaying their writeback to the next frame can cause the completion to get lost on migration. 2) The calling of process_frame from a bh on async completion causes iso tds to get server more often they should, messing up usb sound class device timing. By only processing completed packets, the iso tds get skipped fixing this. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 2838d21..ef32633 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -152,6 +152,7 @@ struct UHCIState { QEMUBH *bh; uint32_t frame_bytes; uint32_t frame_bandwidth; + bool completions_only; UHCIPort ports[NB_PORTS]; /* Interrupts that should be raised at the end of the current frame. */ @@ -891,6 +892,10 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, goto done; } + if (s->completions_only) { + return TD_RESULT_ASYNC_CONT; + } + /* Allocate new packet */ if (q == NULL) { USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f); @@ -960,9 +965,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) } async->done = 1; - if (s->frame_bytes < s->frame_bandwidth) { - qemu_bh_schedule(s->bh); - } + /* Force processing of this packet *now*, needed for migration */ + s->completions_only = true; + qemu_bh_schedule(s->bh); } static int is_valid(uint32_t link) @@ -1054,7 +1059,7 @@ static void uhci_process_frame(UHCIState *s) qhdb_reset(&qhdb); for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) { - if (s->frame_bytes >= s->frame_bandwidth) { + if (!s->completions_only && s->frame_bytes >= s->frame_bandwidth) { /* We've reached the usb 1.1 bandwidth, which is 1280 bytes/frame, stop processing */ trace_usb_uhci_frame_stop_bandwidth(); @@ -1170,6 +1175,7 @@ static void uhci_frame_timer(void *opaque) /* prepare the timer for the next frame */ s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ); s->frame_bytes = 0; + s->completions_only = false; qemu_bh_cancel(s->bh); if (!(s->cmd & UHCI_CMD_RS)) {