From patchwork Fri May 25 12:40:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 161362 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 B2F94B6EE7 for ; Sat, 26 May 2012 00:03:41 +1000 (EST) Received: from localhost ([::1]:33998 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXtqd-0002n6-Aq for incoming@patchwork.ozlabs.org; Fri, 25 May 2012 08:42:27 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42680) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXtp3-00007I-UU for qemu-devel@nongnu.org; Fri, 25 May 2012 08:40:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SXtot-0001BK-Ns for qemu-devel@nongnu.org; Fri, 25 May 2012 08:40:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52576) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXtot-00019u-EG for qemu-devel@nongnu.org; Fri, 25 May 2012 08:40:39 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4PCecN3023101 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 25 May 2012 08:40:38 -0400 Received: from rincewind.home.kraxel.org (ovpn-116-44.ams2.redhat.com [10.36.116.44]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4PCeaUi028816; Fri, 25 May 2012 08:40:36 -0400 Received: by rincewind.home.kraxel.org (Postfix, from userid 500) id 1244B45752; Fri, 25 May 2012 14:40:34 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 25 May 2012 14:40:23 +0200 Message-Id: <1337949634-5264-9-git-send-email-kraxel@redhat.com> In-Reply-To: <1337949634-5264-1-git-send-email-kraxel@redhat.com> References: <1337949634-5264-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 07/18] ehci: add async field to EHCIQueue 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 Keep track whenever a EHCIQueue is part of the async or periodic schedule. This way we don't have to pass around the async flag everywhere but can look it up from the EHCIQueue struct when needed. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 92 ++++++++++++++++++++++++++++------------------------- 1 files changed, 49 insertions(+), 43 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index aa67af6..f363f14 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -364,6 +364,7 @@ struct EHCIQueue { QTAILQ_ENTRY(EHCIQueue) next; uint32_t seen; uint64_t ts; + int async; /* cached data from guest - needs to be flushed * when guest removes an entry (doorbell, handshake sequence) @@ -700,15 +701,16 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async) q = g_malloc0(sizeof(*q)); q->ehci = ehci; q->qhaddr = addr; + q->async = async; QTAILQ_INIT(&q->packets); QTAILQ_INSERT_HEAD(head, q, next); trace_usb_ehci_queue_action(q, "alloc"); return q; } -static void ehci_free_queue(EHCIQueue *q, int async) +static void ehci_free_queue(EHCIQueue *q) { - EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues; + EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues; EHCIPacket *p; trace_usb_ehci_queue_action(q, "free"); @@ -748,7 +750,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) /* allow 0.25 sec idle */ continue; } - ehci_free_queue(q, async); + ehci_free_queue(q); } } @@ -761,7 +763,7 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async) if (q->dev != dev) { continue; } - ehci_free_queue(q, async); + ehci_free_queue(q); } } @@ -771,7 +773,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async) EHCIQueue *q, *tmp; QTAILQ_FOREACH_SAFE(q, head, next, tmp) { - ehci_free_queue(q, async); + ehci_free_queue(q); } } @@ -1806,7 +1808,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async) } /* Section 4.10.2 - paragraph 3 */ -static int ehci_state_advqueue(EHCIQueue *q, int async) +static int ehci_state_advqueue(EHCIQueue *q) { #if 0 /* TO-DO: 4.10.2 - paragraph 2 @@ -1825,27 +1827,27 @@ static int ehci_state_advqueue(EHCIQueue *q, int async) if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) && (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) { q->qtdaddr = q->qh.altnext_qtd; - ehci_set_state(q->ehci, async, EST_FETCHQTD); + ehci_set_state(q->ehci, q->async, EST_FETCHQTD); /* * next qTD is valid */ } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) { q->qtdaddr = q->qh.next_qtd; - ehci_set_state(q->ehci, async, EST_FETCHQTD); + ehci_set_state(q->ehci, q->async, EST_FETCHQTD); /* * no valid qTD, try next QH */ } else { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } return 1; } /* Section 4.10.2 - paragraph 4 */ -static int ehci_state_fetchqtd(EHCIQueue *q, int async) +static int ehci_state_fetchqtd(EHCIQueue *q) { EHCIqtd qtd; EHCIPacket *p; @@ -1865,41 +1867,41 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async) ehci_qh_do_overlay(q); ehci_flush_qh(q); if (p->async == EHCI_ASYNC_INFLIGHT) { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { - ehci_set_state(q->ehci, async, EST_EXECUTING); + ehci_set_state(q->ehci, q->async, EST_EXECUTING); } again = 1; } else if (qtd.token & QTD_TOKEN_ACTIVE) { p = ehci_alloc_packet(q); p->qtdaddr = q->qtdaddr; p->qtd = qtd; - ehci_set_state(q->ehci, async, EST_EXECUTE); + ehci_set_state(q->ehci, q->async, EST_EXECUTE); again = 1; } else { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; } return again; } -static int ehci_state_horizqh(EHCIQueue *q, int async) +static int ehci_state_horizqh(EHCIQueue *q) { int again = 0; - if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) { - ehci_set_fetch_addr(q->ehci, async, q->qh.next); - ehci_set_state(q->ehci, async, EST_FETCHENTRY); + if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) { + ehci_set_fetch_addr(q->ehci, q->async, q->qh.next); + ehci_set_state(q->ehci, q->async, EST_FETCHENTRY); again = 1; } else { - ehci_set_state(q->ehci, async, EST_ACTIVE); + ehci_set_state(q->ehci, q->async, EST_ACTIVE); } return again; } -static void ehci_fill_queue(EHCIPacket *p, int async) +static void ehci_fill_queue(EHCIPacket *p) { EHCIQueue *q = p->queue; EHCIqtd qtd = p->qtd; @@ -1928,7 +1930,7 @@ static void ehci_fill_queue(EHCIPacket *p, int async) } } -static int ehci_state_execute(EHCIQueue *q, int async) +static int ehci_state_execute(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); int again = 0; @@ -1944,16 +1946,16 @@ static int ehci_state_execute(EHCIQueue *q, int async) // TODO write back ptr to async list when done or out of time // TODO Windows does not seem to ever set the MULT field - if (!async) { + if (!q->async) { int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); if (!transactCtr) { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; goto out; } } - if (async) { + if (q->async) { ehci_set_usbsts(q->ehci, USBSTS_REC); } @@ -1966,20 +1968,20 @@ static int ehci_state_execute(EHCIQueue *q, int async) ehci_flush_qh(q); trace_usb_ehci_packet_action(p->queue, p, "async"); p->async = EHCI_ASYNC_INFLIGHT; - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; - ehci_fill_queue(p, async); + ehci_fill_queue(p); goto out; } - ehci_set_state(q->ehci, async, EST_EXECUTING); + ehci_set_state(q->ehci, q->async, EST_EXECUTING); again = 1; out: return again; } -static int ehci_state_executing(EHCIQueue *q, int async) +static int ehci_state_executing(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); int again = 0; @@ -1997,7 +1999,7 @@ static int ehci_state_executing(EHCIQueue *q, int async) } // 4.10.3 - if (!async) { + if (!q->async) { int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); transactCtr--; set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT); @@ -2007,9 +2009,9 @@ static int ehci_state_executing(EHCIQueue *q, int async) /* 4.10.5 */ if (p->usb_status == USB_RET_NAK) { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { - ehci_set_state(q->ehci, async, EST_WRITEBACK); + ehci_set_state(q->ehci, q->async, EST_WRITEBACK); } again = 1; @@ -2020,7 +2022,7 @@ out: } -static int ehci_state_writeback(EHCIQueue *q, int async) +static int ehci_state_writeback(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); int again = 0; @@ -2043,10 +2045,10 @@ static int ehci_state_writeback(EHCIQueue *q, int async) * bit is clear. */ if (q->qh.token & QTD_TOKEN_HALT) { - ehci_set_state(q->ehci, async, EST_HORIZONTALQH); + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; } else { - ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE); + ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE); again = 1; } return again; @@ -2056,8 +2058,7 @@ static int ehci_state_writeback(EHCIQueue *q, int async) * This is the state machine that is common to both async and periodic */ -static void ehci_advance_state(EHCIState *ehci, - int async) +static void ehci_advance_state(EHCIState *ehci, int async) { EHCIQueue *q = NULL; int again; @@ -2074,7 +2075,12 @@ static void ehci_advance_state(EHCIState *ehci, case EST_FETCHQH: q = ehci_state_fetchqh(ehci, async); - again = q ? 1 : 0; + if (q != NULL) { + assert(q->async == async); + again = 1; + } else { + again = 0; + } break; case EST_FETCHITD: @@ -2086,29 +2092,29 @@ static void ehci_advance_state(EHCIState *ehci, break; case EST_ADVANCEQUEUE: - again = ehci_state_advqueue(q, async); + again = ehci_state_advqueue(q); break; case EST_FETCHQTD: - again = ehci_state_fetchqtd(q, async); + again = ehci_state_fetchqtd(q); break; case EST_HORIZONTALQH: - again = ehci_state_horizqh(q, async); + again = ehci_state_horizqh(q); break; case EST_EXECUTE: - again = ehci_state_execute(q, async); + again = ehci_state_execute(q); break; case EST_EXECUTING: assert(q != NULL); - again = ehci_state_executing(q, async); + again = ehci_state_executing(q); break; case EST_WRITEBACK: assert(q != NULL); - again = ehci_state_writeback(q, async); + again = ehci_state_writeback(q); break; default: