summaryrefslogtreecommitdiff
path: root/usb-linux.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2011-06-10 14:00:24 +0200
committerGerd Hoffmann <kraxel@redhat.com>2011-06-23 10:18:37 +0200
commit82887262569d9222befadb6a98bf364beae30a7e (patch)
tree0165f96832e5724550efab71dba3cbf83ec1f3c8 /usb-linux.c
parentb81bcd8aa0f5d16e5590fdc4cf6561b57adab931 (diff)
downloadqemu-82887262569d9222befadb6a98bf364beae30a7e.tar.gz
usb-linux: track inflight iso urb count
Track the number of iso urbs which are currently in flight. Log a message in case the count goes down to zero. Also warn in case many urbs are returned at the same time. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'usb-linux.c')
-rw-r--r--usb-linux.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/usb-linux.c b/usb-linux.c
index f65dcb7ad0..42baafe0a1 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -100,6 +100,7 @@ struct endp_data {
int iso_urb_idx;
int iso_buffer_used;
int max_packet_size;
+ int inflight;
};
struct USBAutoFilter {
@@ -184,7 +185,19 @@ static void clear_iso_started(USBHostDevice *s, int ep)
static void set_iso_started(USBHostDevice *s, int ep)
{
- get_endp(s, ep)->iso_started = 1;
+ struct endp_data *e = get_endp(s, ep);
+ if (!e->iso_started) {
+ e->iso_started = 1;
+ e->inflight = 0;
+ }
+}
+
+static int change_iso_inflight(USBHostDevice *s, int ep, int value)
+{
+ struct endp_data *e = get_endp(s, ep);
+
+ e->inflight += value;
+ return e->inflight;
}
static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
@@ -282,6 +295,7 @@ static void async_complete(void *opaque)
{
USBHostDevice *s = opaque;
AsyncURB *aurb;
+ int urbs = 0;
while (1) {
USBPacket *p;
@@ -289,6 +303,9 @@ static void async_complete(void *opaque)
int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
if (r < 0) {
if (errno == EAGAIN) {
+ if (urbs > 2) {
+ fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
+ }
return;
}
if (errno == ENODEV && !s->closing) {
@@ -306,10 +323,16 @@ static void async_complete(void *opaque)
/* If this is a buffered iso urb mark it as complete and don't do
anything else (it is handled further in usb_host_handle_iso_data) */
if (aurb->iso_frame_idx == -1) {
+ int inflight;
if (aurb->urb.status == -EPIPE) {
set_halt(s, aurb->urb.endpoint & 0xf);
}
aurb->iso_frame_idx = 0;
+ urbs++;
+ inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
+ if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
+ fprintf(stderr, "husb: out of buffers for iso stream\n");
+ }
continue;
}
@@ -670,6 +693,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
break;
}
aurb[i].iso_frame_idx = -1;
+ change_iso_inflight(s, p->devep, +1);
}
}
}