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>
This commit is contained in:
Gerd Hoffmann 2011-06-10 14:00:24 +02:00
parent b81bcd8aa0
commit 8288726256

View File

@ -100,6 +100,7 @@ struct endp_data {
int iso_urb_idx; int iso_urb_idx;
int iso_buffer_used; int iso_buffer_used;
int max_packet_size; int max_packet_size;
int inflight;
}; };
struct USBAutoFilter { struct USBAutoFilter {
@ -184,7 +185,19 @@ static void clear_iso_started(USBHostDevice *s, int ep)
static void set_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) 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; USBHostDevice *s = opaque;
AsyncURB *aurb; AsyncURB *aurb;
int urbs = 0;
while (1) { while (1) {
USBPacket *p; USBPacket *p;
@ -289,6 +303,9 @@ static void async_complete(void *opaque)
int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb); int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
if (r < 0) { if (r < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
if (urbs > 2) {
fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
}
return; return;
} }
if (errno == ENODEV && !s->closing) { 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 /* 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) */ anything else (it is handled further in usb_host_handle_iso_data) */
if (aurb->iso_frame_idx == -1) { if (aurb->iso_frame_idx == -1) {
int inflight;
if (aurb->urb.status == -EPIPE) { if (aurb->urb.status == -EPIPE) {
set_halt(s, aurb->urb.endpoint & 0xf); set_halt(s, aurb->urb.endpoint & 0xf);
} }
aurb->iso_frame_idx = 0; 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; continue;
} }
@ -670,6 +693,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
break; break;
} }
aurb[i].iso_frame_idx = -1; aurb[i].iso_frame_idx = -1;
change_iso_inflight(s, p->devep, +1);
} }
} }
} }