[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [Patch RFC 2/4] usb: add flag to USBPacket to request complete callback after isoc transfer
In order to avoid having to poll for the result of an iso transfer add the possibility to request the "complete" callback which is being used for bulk transfers as well. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- hw/usb/core.c | 2 +- hw/usb/host-libusb.c | 24 ++++++++++++++++++++++-- include/hw/usb.h | 2 ++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index cf34755..bc01713 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -428,7 +428,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p) usb_process_one(p); if (p->status == USB_RET_ASYNC) { /* hcd drivers cannot handle async for isoc */ - assert(p->ep->type != USB_ENDPOINT_XFER_ISOC); + assert(p->ep->type != USB_ENDPOINT_XFER_ISOC || p->isoc_complete); /* using async for interrupt packets breaks migration */ assert(p->ep->type != USB_ENDPOINT_XFER_INT || (dev->flags & (1 << USB_DEV_FLAG_IS_HOST))); diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index a5f9dab..9e39b29 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -120,6 +120,7 @@ struct USBHostIsoXfer { struct libusb_transfer *xfer; bool copy_complete; unsigned int packet; + QTAILQ_HEAD(, USBPacket) callback; QTAILQ_ENTRY(USBHostIsoXfer) next; }; @@ -432,6 +433,17 @@ static void usb_host_req_abort(USBHostRequest *r) /* ------------------------------------------------------------------------ */ +static void usb_host_iso_xfer_complete(USBHostIsoXfer *xfer) +{ + USBHostDevice *s = xfer->ring->host; + USBPacket *packet; + + while ((packet = QTAILQ_FIRST(&xfer->callback)) != NULL) { + QTAILQ_REMOVE(&xfer->callback, packet, isoc_queue); + usb_packet_complete(USB_DEVICE(s), packet); + } +} + static void usb_host_req_complete_iso(struct libusb_transfer *transfer) { USBHostIsoXfer *xfer = transfer->user_data; @@ -451,6 +463,7 @@ static void usb_host_req_complete_iso(struct libusb_transfer *transfer) if (xfer->ring->ep->pid == USB_TOKEN_IN) { QTAILQ_INSERT_TAIL(&xfer->ring->copy, xfer, next); } else { + usb_host_iso_xfer_complete(xfer); QTAILQ_INSERT_TAIL(&xfer->ring->unused, xfer, next); } } @@ -654,6 +667,10 @@ static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p) usb_host_iso_reset_xfer(xfer); QTAILQ_INSERT_TAIL(&ring->copy, xfer, next); } + if (p->isoc_complete) { + p->status = USB_RET_ASYNC; + QTAILQ_INSERT_TAIL(&xfer->callback, p, isoc_queue); + } usb_host_iso_data_copy(xfer, p); if (QTAILQ_EMPTY(&ring->inflight)) { @@ -671,6 +688,7 @@ static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p) rc = libusb_submit_transfer(xfer->xfer); if (rc != 0) { usb_host_libusb_error("libusb_submit_transfer [iso]", rc); + usb_host_iso_xfer_complete(xfer); QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); if (rc == LIBUSB_ERROR_NO_DEVICE) { disconnect = true; @@ -1329,8 +1347,10 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p) } else { usb_host_iso_data_out(s, p); } - trace_usb_host_req_complete(s->bus_num, s->addr, p, - p->status, p->actual_length); + if (p->status != USB_RET_ASYNC) { + trace_usb_host_req_complete(s->bus_num, s->addr, p, + p->status, p->actual_length); + } return; default: p->status = USB_RET_STALL; diff --git a/include/hw/usb.h b/include/hw/usb.h index b20b959..e8f5a63 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -398,6 +398,7 @@ struct USBPacket { uint64_t parameter; /* control transfers */ bool short_not_ok; bool int_req; + bool isoc_complete; int status; /* USB_RET_* status code */ int actual_length; /* Number of bytes actually transferred */ /* Internal use by the USB layer. */ @@ -405,6 +406,7 @@ struct USBPacket { USBCombinedPacket *combined; QTAILQ_ENTRY(USBPacket) queue; QTAILQ_ENTRY(USBPacket) combined_entry; + QTAILQ_ENTRY(USBPacket) isoc_queue; }; struct USBCombinedPacket { -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |