dcavalca / rpms / qemu

Forked from rpms/qemu 11 months ago
Clone

Blame 0102-usb-redir-Dynamically-adjust-iso-buffering-size-base.patch

Justin M. Forbes d4cdad
From cc5740ae8aa68dbbdc690f694b0e55d70f9c49ee Mon Sep 17 00:00:00 2001
Justin M. Forbes d4cdad
From: Hans de Goede <hdegoede@redhat.com>
Justin M. Forbes d4cdad
Date: Mon, 19 Dec 2011 13:42:40 +0100
Justin M. Forbes d4cdad
Subject: [PATCH 102/118] usb-redir: Dynamically adjust iso buffering size
Justin M. Forbes d4cdad
 based on ep interval
Justin M. Forbes d4cdad
Justin M. Forbes d4cdad
Note the bufpq_target_size id stored in the endpoint info struct,
Justin M. Forbes d4cdad
even though it only used once. This is done because it will be
Justin M. Forbes d4cdad
referenced from other code in a follow up patch.
Justin M. Forbes d4cdad
Justin M. Forbes d4cdad
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Justin M. Forbes d4cdad
---
Justin M. Forbes d4cdad
 usb-redir.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++-----
Justin M. Forbes d4cdad
 1 files changed, 47 insertions(+), 5 deletions(-)
Justin M. Forbes d4cdad
Justin M. Forbes d4cdad
diff --git a/usb-redir.c b/usb-redir.c
Justin M. Forbes d4cdad
index 7678f1a..ab2c8fa 100644
Justin M. Forbes d4cdad
--- a/usb-redir.c
Justin M. Forbes d4cdad
+++ b/usb-redir.c
Justin M. Forbes d4cdad
@@ -61,6 +61,7 @@ struct endp_data {
Justin M. Forbes d4cdad
     uint8_t interrupt_started;
Justin M. Forbes d4cdad
     uint8_t interrupt_error;
Justin M. Forbes d4cdad
     QTAILQ_HEAD(, buf_packet) bufpq;
Justin M. Forbes d4cdad
+    int bufpq_target_size;
Justin M. Forbes d4cdad
 };
Justin M. Forbes d4cdad
Justin M. Forbes d4cdad
 struct USBRedirDevice {
Justin M. Forbes d4cdad
@@ -332,15 +333,41 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
Justin M. Forbes d4cdad
                                      uint8_t ep)
Justin M. Forbes d4cdad
 {
Justin M. Forbes d4cdad
     int status, len;
Justin M. Forbes d4cdad
-
Justin M. Forbes d4cdad
     if (!dev->endpoint[EP2I(ep)].iso_started &&
Justin M. Forbes d4cdad
             !dev->endpoint[EP2I(ep)].iso_error) {
Justin M. Forbes d4cdad
         struct usb_redir_start_iso_stream_header start_iso = {
Justin M. Forbes d4cdad
             .endpoint = ep,
Justin M. Forbes d4cdad
-            /* TODO maybe do something with these depending on ep interval? */
Justin M. Forbes d4cdad
-            .pkts_per_urb = 32,
Justin M. Forbes d4cdad
-            .no_urbs = 3,
Justin M. Forbes d4cdad
         };
Justin M. Forbes d4cdad
+        int pkts_per_sec;
Justin M. Forbes d4cdad
+
Justin M. Forbes d4cdad
+        if (dev->dev.speed == USB_SPEED_HIGH)
Justin M. Forbes d4cdad
+            pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval;
Justin M. Forbes d4cdad
+        else
Justin M. Forbes d4cdad
+            pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval;
Justin M. Forbes d4cdad
+        /* Testing has shown that we need circa 60 ms buffer */
Justin M. Forbes d4cdad
+        dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000;
Justin M. Forbes d4cdad
+
Justin M. Forbes d4cdad
+        /* Aim for approx 100 interrupts / second on the client to
Justin M. Forbes d4cdad
+           balance latency and interrupt load */
Justin M. Forbes d4cdad
+        start_iso.pkts_per_urb = pkts_per_sec / 100;
Justin M. Forbes d4cdad
+        if (start_iso.pkts_per_urb < 1) {
Justin M. Forbes d4cdad
+            start_iso.pkts_per_urb = 1;
Justin M. Forbes d4cdad
+        } else if (start_iso.pkts_per_urb > 32) {
Justin M. Forbes d4cdad
+            start_iso.pkts_per_urb = 32;
Justin M. Forbes d4cdad
+        }
Justin M. Forbes d4cdad
+
Justin M. Forbes d4cdad
+        start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
Justin M. Forbes d4cdad
+                             start_iso.pkts_per_urb - 1) /
Justin M. Forbes d4cdad
+                            start_iso.pkts_per_urb;
Justin M. Forbes d4cdad
+        /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
Justin M. Forbes d4cdad
+           as overflow buffer. Also see the usbredir protocol documentation */
Justin M. Forbes d4cdad
+        if (!(ep & USB_DIR_IN)) {
Justin M. Forbes d4cdad
+            start_iso.no_urbs *= 2;
Justin M. Forbes d4cdad
+        }
Justin M. Forbes d4cdad
+        if (start_iso.no_urbs > 16) {
Justin M. Forbes d4cdad
+            start_iso.no_urbs = 16;
Justin M. Forbes d4cdad
+        }
Justin M. Forbes d4cdad
+
Justin M. Forbes d4cdad
         /* No id, we look at the ep when receiving a status back */
Justin M. Forbes d4cdad
         usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
Justin M. Forbes d4cdad
         usbredirparser_do_write(dev->parser);
Justin M. Forbes d4cdad
@@ -961,9 +988,24 @@ static void usbredir_ep_info(void *priv,
Justin M. Forbes d4cdad
         dev->endpoint[i].type = ep_info->type[i];
Justin M. Forbes d4cdad
         dev->endpoint[i].interval = ep_info->interval[i];
Justin M. Forbes d4cdad
         dev->endpoint[i].interface = ep_info->interface[i];
Justin M. Forbes d4cdad
-        if (dev->endpoint[i].type != usb_redir_type_invalid) {
Justin M. Forbes d4cdad
+        switch (dev->endpoint[i].type) {
Justin M. Forbes d4cdad
+        case usb_redir_type_invalid:
Justin M. Forbes d4cdad
+            break;
Justin M. Forbes d4cdad
+        case usb_redir_type_iso:
Justin M. Forbes d4cdad
+        case usb_redir_type_interrupt:
Justin M. Forbes d4cdad
+            if (dev->endpoint[i].interval == 0) {
Justin M. Forbes d4cdad
+                ERROR("Received 0 interval for isoc or irq endpoint\n");
Justin M. Forbes d4cdad
+                usbredir_device_disconnect(dev);
Justin M. Forbes d4cdad
+            }
Justin M. Forbes d4cdad
+            /* Fall through */
Justin M. Forbes d4cdad
+        case usb_redir_type_control:
Justin M. Forbes d4cdad
+        case usb_redir_type_bulk:
Justin M. Forbes d4cdad
             DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
Justin M. Forbes d4cdad
                     dev->endpoint[i].type, dev->endpoint[i].interface);
Justin M. Forbes d4cdad
+            break;
Justin M. Forbes d4cdad
+        default:
Justin M. Forbes d4cdad
+            ERROR("Received invalid endpoint type\n");
Justin M. Forbes d4cdad
+            usbredir_device_disconnect(dev);
Justin M. Forbes d4cdad
         }
Justin M. Forbes d4cdad
     }
Justin M. Forbes d4cdad
 }
Justin M. Forbes d4cdad
-- 
Justin M. Forbes d4cdad
1.7.7.5
Justin M. Forbes d4cdad