d4cdad5
From b8e632d175063770655e75507de85ae873fa6c2d Mon Sep 17 00:00:00 2001
d4cdad5
From: Hans de Goede <hdegoede@redhat.com>
d4cdad5
Date: Tue, 20 Dec 2011 16:54:25 +0100
d4cdad5
Subject: [PATCH 104/118] usb-redir: Try to keep our buffer size near the
d4cdad5
 target size
d4cdad5
d4cdad5
Before this patch we would allow the (iso) buffer to grow unlimited
d4cdad5
(and it would under certain circumstances) leading to way too high
d4cdad5
latencies for iso data streams.
d4cdad5
d4cdad5
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
d4cdad5
---
d4cdad5
 usb-redir.c |   30 +++++++++++++++++++++++++++---
d4cdad5
 1 files changed, 27 insertions(+), 3 deletions(-)
d4cdad5
d4cdad5
diff --git a/usb-redir.c b/usb-redir.c
d4cdad5
index 17ea7a7..88d941a 100644
d4cdad5
--- a/usb-redir.c
d4cdad5
+++ b/usb-redir.c
d4cdad5
@@ -61,6 +61,7 @@ struct endp_data {
d4cdad5
     uint8_t interrupt_started;
d4cdad5
     uint8_t interrupt_error;
d4cdad5
     uint8_t bufpq_prefilled;
d4cdad5
+    uint8_t bufpq_dropping_packets;
d4cdad5
     QTAILQ_HEAD(, buf_packet) bufpq;
d4cdad5
     int bufpq_size;
d4cdad5
     int bufpq_target_size;
d4cdad5
@@ -290,16 +291,34 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
d4cdad5
     }
d4cdad5
 }
d4cdad5
d4cdad5
-static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
d4cdad5
+static void bufp_alloc(USBRedirDevice *dev,
d4cdad5
     uint8_t *data, int len, int status, uint8_t ep)
d4cdad5
 {
d4cdad5
-    struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet));
d4cdad5
+    struct buf_packet *bufp;
d4cdad5
+
d4cdad5
+    if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
d4cdad5
+        dev->endpoint[EP2I(ep)].bufpq_size >
d4cdad5
+            2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
d4cdad5
+        DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
d4cdad5
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
d4cdad5
+    }
d4cdad5
+    /* Since we're interupting the stream anyways, drop enough packets to get
d4cdad5
+       back to our target buffer size */
d4cdad5
+    if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
d4cdad5
+        if (dev->endpoint[EP2I(ep)].bufpq_size >
d4cdad5
+                dev->endpoint[EP2I(ep)].bufpq_target_size) {
d4cdad5
+            free(data);
d4cdad5
+            return;
d4cdad5
+        }
d4cdad5
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
d4cdad5
+    }
d4cdad5
+
d4cdad5
+    bufp = g_malloc(sizeof(struct buf_packet));
d4cdad5
     bufp->data   = data;
d4cdad5
     bufp->len    = len;
d4cdad5
     bufp->status = status;
d4cdad5
     QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
d4cdad5
     dev->endpoint[EP2I(ep)].bufpq_size++;
d4cdad5
-    return bufp;
d4cdad5
 }
d4cdad5
d4cdad5
 static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
d4cdad5
@@ -378,6 +397,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
d4cdad5
         DPRINTF("iso stream started ep %02X\n", ep);
d4cdad5
         dev->endpoint[EP2I(ep)].iso_started = 1;
d4cdad5
         dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
d4cdad5
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
d4cdad5
     }
d4cdad5
d4cdad5
     if (ep & USB_DIR_IN) {
d4cdad5
@@ -504,6 +524,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
d4cdad5
             usbredirparser_do_write(dev->parser);
d4cdad5
             DPRINTF("interrupt recv started ep %02X\n", ep);
d4cdad5
             dev->endpoint[EP2I(ep)].interrupt_started = 1;
d4cdad5
+            /* We don't really want to drop interrupt packets ever, but
d4cdad5
+               having some upper limit to how much we buffer is good. */
d4cdad5
+            dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
d4cdad5
+            dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
d4cdad5
         }
d4cdad5
d4cdad5
         intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
d4cdad5
-- 
d4cdad5
1.7.7.5
d4cdad5