Patchwork [15/18] usb: keep track of packet owner.

login
register
mail settings
Submitter Gerd Hoffmann
Date May 16, 2011, 7:56 p.m.
Message ID <1305575782-31766-16-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/95829/
State New
Headers show

Comments

Gerd Hoffmann - May 16, 2011, 7:56 p.m.
Keep track of the device which owns the usb packet for async processing.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.c |   32 ++++++++++++++++++++++++++++++++
 hw/usb.h |   18 +++---------------
 2 files changed, 35 insertions(+), 15 deletions(-)

Patch

diff --git a/hw/usb.c b/hw/usb.c
index 966cb0f..8a9a7fc 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -313,6 +313,38 @@  int usb_handle_packet(USBDevice *dev, USBPacket *p)
 {
     int ret;
 
+    assert(p->owner == NULL);
     ret = dev->info->handle_packet(dev, p);
+    if (ret == USB_RET_ASYNC) {
+        if (p->owner == NULL) {
+            p->owner = dev;
+        } else {
+            /* We'll end up here when usb_handle_packet is called
+             * recursively due to a hub being in the chain.  Nothing
+             * to do.  Leave p->owner pointing to the device, not the
+             * hub. */;
+        }
+    }
     return ret;
 }
+
+/* Notify the controller that an async packet is complete.  This should only
+   be called for packets previously deferred by returning USB_RET_ASYNC from
+   handle_packet. */
+void usb_packet_complete(USBDevice *dev, USBPacket *p)
+{
+    /* Note: p->owner != dev is possible in case dev is a hub */
+    assert(p->owner != NULL);
+    dev->port->ops->complete(dev, p);
+    p->owner = NULL;
+}
+
+/* Cancel an active packet.  The packed must have been deferred by
+   returning USB_RET_ASYNC from handle_packet, and not yet
+   completed.  */
+void usb_cancel_packet(USBPacket * p)
+{
+    assert(p->owner != NULL);
+    p->cancel_cb(p, p->cancel_opaque);
+    p->owner = NULL;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 6889467..80e8e90 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -262,11 +262,14 @@  struct USBPacket {
     uint8_t *data;
     int len;
     /* Internal use by the USB layer.  */
+    USBDevice *owner;
     USBCallback *cancel_cb;
     void *cancel_opaque;
 };
 
 int usb_handle_packet(USBDevice *dev, USBPacket *p);
+void usb_packet_complete(USBDevice *dev, USBPacket *p);
+void usb_cancel_packet(USBPacket * p);
 
 /* Defer completion of a USB packet.  The hadle_packet routine should then
    return USB_RET_ASYNC.  Packets that complete immediately (before
@@ -278,21 +281,6 @@  static inline void usb_defer_packet(USBPacket *p, USBCallback *cancel,
     p->cancel_opaque = opaque;
 }
 
-/* Notify the controller that an async packet is complete.  This should only
-   be called for packets previously deferred with usb_defer_packet, and
-   should never be called from within handle_packet.  */
-static inline void usb_packet_complete(USBDevice *dev, USBPacket *p)
-{
-    dev->port->ops->complete(dev, p);
-}
-
-/* Cancel an active packet.  The packed must have been deferred with
-   usb_defer_packet,  and not yet completed.  */
-static inline void usb_cancel_packet(USBPacket * p)
-{
-    p->cancel_cb(p, p->cancel_opaque);
-}
-
 void usb_attach(USBPort *port, USBDevice *dev);
 void usb_wakeup(USBDevice *dev);
 int usb_generic_handle_packet(USBDevice *s, USBPacket *p);