From patchwork Mon Oct 8 07:51:31 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 189943 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 377862C0223 for ; Mon, 8 Oct 2012 19:27:35 +1100 (EST) Received: from localhost ([::1]:48975 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TL87E-0003nI-Ac for incoming@patchwork.ozlabs.org; Mon, 08 Oct 2012 03:51:04 -0400 Received: from eggs.gnu.org ([208.118.235.92]:48407) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TL86W-0001i3-4c for qemu-devel@nongnu.org; Mon, 08 Oct 2012 03:50:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TL86U-0006Fp-3M for qemu-devel@nongnu.org; Mon, 08 Oct 2012 03:50:20 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54560) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TL86T-0006Fg-RP for qemu-devel@nongnu.org; Mon, 08 Oct 2012 03:50:18 -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 q987oHdB000806 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 8 Oct 2012 03:50:17 -0400 Received: from shalem.localdomain.com (vpn1-7-79.ams2.redhat.com [10.36.7.79]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q987o59j012329; Mon, 8 Oct 2012 03:50:16 -0400 From: Hans de Goede To: Gerd Hoffmann Date: Mon, 8 Oct 2012 09:51:31 +0200 Message-Id: <1349682696-3046-8-git-send-email-hdegoede@redhat.com> In-Reply-To: <1349682696-3046-1-git-send-email-hdegoede@redhat.com> References: <1349682696-3046-1-git-send-email-hdegoede@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: Hans de Goede , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 07/12] uhci: Add support for input queuing 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 Signed-off-by: Hans de Goede --- hw/usb/hcd-uhci.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 124d43a..63f2161 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -678,6 +678,13 @@ static void uhci_wakeup(USBPort *port1) } } +static void uhci_remove_from_queue(USBPort *port, USBPacket *p) +{ + UHCIAsync *async = DO_UPCAST(UHCIAsync, packet, p); + uhci_async_unlink(async); + uhci_async_cancel(async); +} + static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) { USBDevice *dev; @@ -818,7 +825,8 @@ out: } static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, - uint32_t *int_mask, bool queuing) + uint32_t *int_mask, bool queuing, + struct USBEndpoint **ep_ret) { UHCIAsync *async; int len = 0, max_len; @@ -862,6 +870,9 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); + if (ep_ret) { + *ep_ret = ep; + } usb_packet_setup(&async->packet, pid, ep, addr); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); @@ -875,6 +886,8 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, break; case USB_TOKEN_IN: + async->packet.short_not_ok = ((td->ctrl & TD_CTRL_SPD) != 0); + async->packet.int_req = ((td->ctrl & TD_CTRL_IOC) != 0); len = usb_handle_packet(dev, &async->packet); break; @@ -975,7 +988,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr) return 0; } -static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) +static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep) { uint32_t int_mask = 0; uint32_t plink = td->link; @@ -984,7 +997,8 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) int ret; ptd.ctrl = td->ctrl; - while (is_valid(plink) && !(ptd.ctrl & TD_CTRL_SPD)) { + while (is_valid(plink) && + (usb_ep_input_pipeline(ep) || !(ptd.ctrl & TD_CTRL_SPD))) { pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd)); le32_to_cpus(&ptd.link); le32_to_cpus(&ptd.ctrl); @@ -997,7 +1011,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) break; } trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); - ret = uhci_handle_td(s, plink, &ptd, &int_mask, true); + ret = uhci_handle_td(s, plink, &ptd, &int_mask, true, NULL); if (ret == TD_RESULT_ASYNC_CONT) { break; } @@ -1005,12 +1019,14 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) assert(int_mask == 0); plink = ptd.link; } + usb_ep_process_queue(ep); } static void uhci_process_frame(UHCIState *s) { uint32_t frame_addr, link, old_td_ctrl, val, int_mask; uint32_t curr_qh, td_count = 0; + struct USBEndpoint *curr_ep; int cnt, ret; UHCI_TD td; UHCI_QH qh; @@ -1081,7 +1097,7 @@ static void uhci_process_frame(UHCIState *s) trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; - ret = uhci_handle_td(s, link, &td, &int_mask, false); + ret = uhci_handle_td(s, link, &td, &int_mask, false, &curr_ep); if (old_td_ctrl != td.ctrl) { /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); @@ -1100,7 +1116,7 @@ static void uhci_process_frame(UHCIState *s) case TD_RESULT_ASYNC_START: trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); - uhci_fill_queue(s, &td); + uhci_fill_queue(s, &td, curr_ep); link = curr_qh ? qh.link : td.link; continue; @@ -1202,6 +1218,7 @@ static USBPortOps uhci_port_ops = { .child_detach = uhci_child_detach, .wakeup = uhci_wakeup, .complete = uhci_async_complete, + .remove_from_queue = uhci_remove_from_queue, }; static USBBusOps uhci_bus_ops = { @@ -1238,6 +1255,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev) USBPort *ports[NB_PORTS]; for(i = 0; i < NB_PORTS; i++) { ports[i] = &s->ports[i].port; + ports[i]->supports_queuing = true; } if (usb_register_companion(s->masterbus, ports, NB_PORTS, s->firstport, s, &uhci_port_ops, @@ -1247,6 +1265,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev) } else { usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev); for (i = 0; i < NB_PORTS; i++) { + s->ports[i].port.supports_queuing = true; usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); }