diff mbox

[2/5] usb-redir: Dynamically adjust iso buffering size based on ep interval

Message ID 1324552358-5234-2-git-send-email-hdegoede@redhat.com
State New
Headers show

Commit Message

Hans de Goede Dec. 22, 2011, 11:12 a.m. UTC
Note the bufpq_target_size id stored in the endpoint info struct,
even though it only used once. This is done because it will be
referenced from other code in a follow up patch.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 usb-redir.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 47 insertions(+), 5 deletions(-)

Comments

Gerd Hoffmann Jan. 6, 2012, 9:51 a.m. UTC | #1
On 12/22/11 12:12, Hans de Goede wrote:
> Note the bufpq_target_size id stored in the endpoint info struct,
> even though it only used once. This is done because it will be
> referenced from other code in a follow up patch.

=== checkpatch complains ===
WARNING: braces {} are necessary for all arms of this statement
#29: FILE: usb-redir.c:343:
+        if (dev->dev.speed == USB_SPEED_HIGH)
[...]
+        else
[...]

total: 0 errors, 1 warnings, 77 lines checked

cheers,
  Gerd

Hint:
http://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html
diff mbox

Patch

diff --git a/usb-redir.c b/usb-redir.c
index 477c609..0a1157b 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -61,6 +61,7 @@  struct endp_data {
     uint8_t interrupt_started;
     uint8_t interrupt_error;
     QTAILQ_HEAD(, buf_packet) bufpq;
+    int bufpq_target_size;
 };
 
 struct USBRedirDevice {
@@ -342,15 +343,41 @@  static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
                                      uint8_t ep)
 {
     int status, len;
-
     if (!dev->endpoint[EP2I(ep)].iso_started &&
             !dev->endpoint[EP2I(ep)].iso_error) {
         struct usb_redir_start_iso_stream_header start_iso = {
             .endpoint = ep,
-            /* TODO maybe do something with these depending on ep interval? */
-            .pkts_per_urb = 32,
-            .no_urbs = 3,
         };
+        int pkts_per_sec;
+
+        if (dev->dev.speed == USB_SPEED_HIGH)
+            pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval;
+        else
+            pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval;
+        /* Testing has shown that we need circa 60 ms buffer */
+        dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000;
+
+        /* Aim for approx 100 interrupts / second on the client to
+           balance latency and interrupt load */
+        start_iso.pkts_per_urb = pkts_per_sec / 100;
+        if (start_iso.pkts_per_urb < 1) {
+            start_iso.pkts_per_urb = 1;
+        } else if (start_iso.pkts_per_urb > 32) {
+            start_iso.pkts_per_urb = 32;
+        }
+
+        start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
+                             start_iso.pkts_per_urb - 1) /
+                            start_iso.pkts_per_urb;
+        /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
+           as overflow buffer. Also see the usbredir protocol documentation */
+        if (!(ep & USB_DIR_IN)) {
+            start_iso.no_urbs *= 2;
+        }
+        if (start_iso.no_urbs > 16) {
+            start_iso.no_urbs = 16;
+        }
+
         /* No id, we look at the ep when receiving a status back */
         usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
         usbredirparser_do_write(dev->parser);
@@ -988,9 +1015,24 @@  static void usbredir_ep_info(void *priv,
         dev->endpoint[i].type = ep_info->type[i];
         dev->endpoint[i].interval = ep_info->interval[i];
         dev->endpoint[i].interface = ep_info->interface[i];
-        if (dev->endpoint[i].type != usb_redir_type_invalid) {
+        switch (dev->endpoint[i].type) {
+        case usb_redir_type_invalid:
+            break;
+        case usb_redir_type_iso:
+        case usb_redir_type_interrupt:
+            if (dev->endpoint[i].interval == 0) {
+                ERROR("Received 0 interval for isoc or irq endpoint\n");
+                usbredir_device_disconnect(dev);
+            }
+            /* Fall through */
+        case usb_redir_type_control:
+        case usb_redir_type_bulk:
             DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
                     dev->endpoint[i].type, dev->endpoint[i].interface);
+            break;
+        default:
+            ERROR("Received invalid endpoint type\n");
+            usbredir_device_disconnect(dev);
         }
     }
 }