From mboxrd@z Thu Jan 1 00:00:00 1970 From: Juergen Gross Subject: [Patch RFC 2/4] usb: add flag to USBPacket to request complete callback after isoc transfer Date: Thu, 16 Jul 2015 17:47:36 +0200 Message-ID: <1437061658-11769-3-git-send-email-jgross@suse.com> References: <1437061658-11769-1-git-send-email-jgross@suse.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1437061658-11769-1-git-send-email-jgross@suse.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: kraxel@redhat.com, stefano.stabellini@eu.citrix.com, xen-devel@lists.xensource.com Cc: Juergen Gross List-Id: xen-devel@lists.xenproject.org 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 --- 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