aboutsummaryrefslogtreecommitdiffstats
path: root/usb-redir.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-01-10 14:13:07 +0100
committerGerd Hoffmann <kraxel@redhat.com>2012-01-17 09:44:51 +0100
commit81fd7b7495d2a4c92483ed14075e376729c94ab4 (patch)
treea867066898730119fd03c2aba1608a34f3b46939 /usb-redir.c
parente15378847919144b99ead1587a54168f1dd3ddf9 (diff)
usb-redir: Try to keep our buffer size near the target size
Before this patch we would allow the (iso) buffer to grow unlimited (and it would under certain circumstances) leading to way too high latencies for iso data streams. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'usb-redir.c')
-rw-r--r--usb-redir.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/usb-redir.c b/usb-redir.c
index cdd929a60..147e237fa 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -61,6 +61,7 @@ struct endp_data {
uint8_t interrupt_started;
uint8_t interrupt_error;
uint8_t bufpq_prefilled;
+ uint8_t bufpq_dropping_packets;
QTAILQ_HEAD(, buf_packet) bufpq;
int bufpq_size;
int bufpq_target_size;
@@ -290,16 +291,34 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
}
}
-static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
+static void bufp_alloc(USBRedirDevice *dev,
uint8_t *data, int len, int status, uint8_t ep)
{
- struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet));
+ struct buf_packet *bufp;
+
+ if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
+ dev->endpoint[EP2I(ep)].bufpq_size >
+ 2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
+ DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
+ }
+ /* Since we're interupting the stream anyways, drop enough packets to get
+ back to our target buffer size */
+ if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
+ if (dev->endpoint[EP2I(ep)].bufpq_size >
+ dev->endpoint[EP2I(ep)].bufpq_target_size) {
+ free(data);
+ return;
+ }
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
+ }
+
+ bufp = g_malloc(sizeof(struct buf_packet));
bufp->data = data;
bufp->len = len;
bufp->status = status;
QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
dev->endpoint[EP2I(ep)].bufpq_size++;
- return bufp;
}
static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
@@ -379,6 +398,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
DPRINTF("iso stream started ep %02X\n", ep);
dev->endpoint[EP2I(ep)].iso_started = 1;
dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
}
if (ep & USB_DIR_IN) {
@@ -505,6 +525,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
usbredirparser_do_write(dev->parser);
DPRINTF("interrupt recv started ep %02X\n", ep);
dev->endpoint[EP2I(ep)].interrupt_started = 1;
+ /* We don't really want to drop interrupt packets ever, but
+ having some upper limit to how much we buffer is good. */
+ dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
}
intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);