From patchwork Mon Oct 15 10:38:27 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: 191535 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 C44D62C00AE for ; Mon, 15 Oct 2012 22:20:34 +1100 (EST) Received: from localhost ([::1]:34567 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TNi66-000123-IW for incoming@patchwork.ozlabs.org; Mon, 15 Oct 2012 06:40:34 -0400 Received: from eggs.gnu.org ([208.118.235.92]:44098) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TNi42-0005wK-4c for qemu-devel@nongnu.org; Mon, 15 Oct 2012 06:38:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TNi40-0003ve-98 for qemu-devel@nongnu.org; Mon, 15 Oct 2012 06:38:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:63195) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TNi40-0003vU-1H for qemu-devel@nongnu.org; Mon, 15 Oct 2012 06:38:24 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9FAcNld000538 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 15 Oct 2012 06:38:23 -0400 Received: from localhost.localdomain.com (vpn1-5-26.ams2.redhat.com [10.36.5.26]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9FAc0Eg008943; Mon, 15 Oct 2012 06:38:22 -0400 From: Hans de Goede To: qemu-devel@nongnu.org Date: Mon, 15 Oct 2012 12:38:27 +0200 Message-Id: <1350297511-25437-19-git-send-email-hdegoede@redhat.com> In-Reply-To: <1350297511-25437-1-git-send-email-hdegoede@redhat.com> References: <1350297511-25437-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 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 , Gerd Hoffmann Subject: [Qemu-devel] [PATCH 18/22] usb-redir: Add support for input pipelining 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/redirect.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 030522e..f715281 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -29,6 +29,7 @@ #include "qemu-timer.h" #include "monitor.h" #include "sysemu.h" +#include "iov.h" #include #include @@ -322,6 +323,11 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + if (p->combined) { + usb_combined_packet_cancel(udev, p); + return; + } + packet_id_queue_add(&dev->cancelled, p->id); usbredirparser_send_cancel_data_packet(dev->parser, p->id); usbredirparser_do_write(dev->parser); @@ -575,17 +581,18 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { struct usb_redir_bulk_packet_header bulk_packet; + size_t size = (p->combined) ? p->combined->iov.size : p->iov.size; - DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id); if (usbredir_already_in_flight(dev, p->id)) { return USB_RET_ASYNC; } bulk_packet.endpoint = ep; - bulk_packet.length = p->iov.size; + bulk_packet.length = size; bulk_packet.stream_id = 0; - bulk_packet.length_high = p->iov.size >> 16; + bulk_packet.length_high = size >> 16; assert(bulk_packet.length_high == 0 || usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_32bits_bulk_length)); @@ -594,11 +601,16 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, usbredirparser_send_bulk_packet(dev->parser, p->id, &bulk_packet, NULL, 0); } else { - uint8_t buf[p->iov.size]; - usb_packet_copy(p, buf, p->iov.size); - usbredir_log_data(dev, "bulk data out:", buf, p->iov.size); + uint8_t buf[size]; + if (p->combined) { + iov_to_buf(p->combined->iov.iov, p->combined->iov.niov, + 0, buf, size); + } else { + usb_packet_copy(p, buf, size); + } + usbredir_log_data(dev, "bulk data out:", buf, size); usbredirparser_send_bulk_packet(dev->parser, p->id, - &bulk_packet, buf, p->iov.size); + &bulk_packet, buf, size); } usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; @@ -715,6 +727,9 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p) case USB_ENDPOINT_XFER_ISOC: return usbredir_handle_iso_data(dev, p, ep); case USB_ENDPOINT_XFER_BULK: + if (p->pid == USB_TOKEN_IN && p->ep->pipeline) { + return USB_RET_ADD_TO_QUEUE; + } return usbredir_handle_bulk_data(dev, p, ep); case USB_ENDPOINT_XFER_INT: return usbredir_handle_interrupt_data(dev, p, ep); @@ -725,6 +740,20 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p) } } +static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) +{ + if (ep->pid == USB_TOKEN_IN && ep->pipeline) { + usb_ep_combine_input_packets(ep); + } +} + +static int usbredir_handle_combined_data(USBDevice *udev, USBPacket *p) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + + return usbredir_handle_bulk_data(dev, p, p->ep->nr | USB_DIR_IN); +} + static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, int config) { @@ -1310,6 +1339,11 @@ static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) if (uep->pid == USB_TOKEN_OUT) { uep->pipeline = true; } + if (uep->pid == USB_TOKEN_IN && uep->max_packet_size != 0 && + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_32bits_bulk_length)) { + uep->pipeline = true; + } } static void usbredir_ep_info(void *priv, @@ -1492,11 +1526,17 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, p = usbredir_find_packet_by_id(dev, ep, id); if (p) { + size_t size = (p->combined) ? p->combined->iov.size : p->iov.size; len = usbredir_handle_status(dev, bulk_packet->status, len); if (len > 0) { usbredir_log_data(dev, "bulk data in:", data, data_len); - if (data_len <= p->iov.size) { - usb_packet_copy(p, data, data_len); + if (data_len <= size) { + if (p->combined) { + iov_from_buf(p->combined->iov.iov, p->combined->iov.niov, + 0, data, data_len); + } else { + usb_packet_copy(p, data, data_len); + } } else { ERROR("bulk got more data then requested (%d > %zd)\n", data_len, p->iov.size); @@ -1504,7 +1544,11 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, } } p->result = len; - usb_packet_complete(&dev->dev, p); + if (p->pid == USB_TOKEN_IN && p->ep->pipeline) { + usb_combined_input_packet_complete(&dev->dev, p); + } else { + usb_packet_complete(&dev->dev, p); + } } free(data); } @@ -1911,6 +1955,9 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) uc->handle_reset = usbredir_handle_reset; uc->handle_data = usbredir_handle_data; uc->handle_control = usbredir_handle_control; + uc->flush_ep_queue = usbredir_flush_ep_queue; + uc->handle_combined_data = usbredir_handle_combined_data; + uc->cancel_combined_packet = usbredir_cancel_packet; dc->vmsd = &usbredir_vmstate; dc->props = usbredir_properties; }