[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.