qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: Hans de Goede <hdegoede@redhat.com>, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 4/8] usb-redir: Add support for input pipelining
Date: Wed, 31 Oct 2012 13:47:12 +0100	[thread overview]
Message-ID: <1351687636-14253-5-git-send-email-hdegoede@redhat.com> (raw)
In-Reply-To: <1351687636-14253-1-git-send-email-hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/redirect.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index a24ff63..d7a08b2 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 <dirent.h>
 #include <sys/ioctl.h>
@@ -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,10 @@ 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->state == USB_PACKET_SETUP && 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 +741,13 @@ 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_set_config(USBRedirDevice *dev, USBPacket *p,
                                 int config)
 {
@@ -1306,6 +1329,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,
@@ -1488,11 +1516,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);
@@ -1500,7 +1534,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);
 }
@@ -1907,6 +1945,7 @@ 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;
     dc->vmsd           = &usbredir_vmstate;
     dc->props          = usbredir_properties;
 }
-- 
1.7.12.1

  parent reply	other threads:[~2012-10-31 12:45 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-31 12:47 [Qemu-devel] usb input pipelining patches v3 Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 1/8] usb: Add packet combining functions Hans de Goede
2012-11-01 10:08   ` Gerd Hoffmann
2012-11-01 13:14     ` Hans de Goede
2012-11-01 13:28       ` Hans de Goede
2012-11-01 13:59     ` Hans de Goede
2012-11-01 14:23       ` Gerd Hoffmann
2012-11-01 16:17         ` Hans de Goede
2012-11-01 16:42           ` Gerd Hoffmann
2012-11-01 19:07             ` Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 2/8] combined-packet: Add a workaround for Linux usbfs + live migration Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 3/8] usb-redir: Add support for 32 bits bulk packet length Hans de Goede
2012-10-31 12:47 ` Hans de Goede [this message]
2012-11-01 10:10   ` [Qemu-devel] [PATCH 4/8] usb-redir: Add support for input pipelining Gerd Hoffmann
2012-11-01 13:16     ` Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 5/8] usb-redir: Add an usbredir_setup_usb_eps() helper function Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 6/8] usb-redir: Use reject rather the disconnect on bad ep info Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 7/8] usb-redir: Allow to attach USB 2.0 devices to 1.1 host controller Hans de Goede
2012-10-31 12:47 ` [Qemu-devel] [PATCH 8/8] usb-redir: Allow redirecting super speed devices to high speed controllers Hans de Goede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1351687636-14253-5-git-send-email-hdegoede@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).