From f09424e39f22ba2f245d0db93c2daa540bc1d04d Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 23 Jun 2011 12:41:56 -0300
Subject: [RHEL6 qemu-kvm PATCH 081/115] usb-linux: walk async urb list in cancel

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1308832951-8995-81-git-send-email-kraxel@redhat.com>
Patchwork-id: 28407
O-Subject: [RHEL-6.2 kvm PATCH 080/115] usb-linux: walk async urb list in cancel
Bugzilla: 561414 632299 645351 711354
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>

Lookup async urbs which are to be canceled using the linked list
instead of the direct opaque pointer.  There are two reasons we
are doing that:  First, to avoid the opaque poiner to the callback,
which is needed for upcoming cleanups.  Second, because we might
need multiple urbs per request for highspeed support, so a single
opaque pointer doesn't cut it any more anyway.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 227ebeb5353681b206a74db44530e60a46c24275)
---
 usb-linux.c |   28 +++++++++++++++++-----------
 1 files changed, 17 insertions(+), 11 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 usb-linux.c |   28 +++++++++++++++++-----------
 1 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/usb-linux.c b/usb-linux.c
index f3a0344..5ea0b79 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -314,19 +314,25 @@ static void async_complete(void *opaque)
     }
 }
 
-static void async_cancel(USBPacket *unused, void *opaque)
+static void async_cancel(USBPacket *p, void *opaque)
 {
-    AsyncURB *aurb = opaque;
-    USBHostDevice *s = aurb->hdev;
+    USBHostDevice *s = opaque;
+    AsyncURB *aurb;
 
-    DPRINTF("husb: async cancel. aurb %p\n", aurb);
+    QLIST_FOREACH(aurb, &s->aurbs, next) {
+        if (p != aurb->packet) {
+            continue;
+        }
 
-    /* Mark it as dead (see async_complete above) */
-    aurb->packet = NULL;
+        DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
 
-    int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
-    if (r < 0) {
-        DPRINTF("husb: async. discard urb failed errno %d\n", errno);
+        /* Mark it as dead (see async_complete above) */
+        aurb->packet = NULL;
+
+        int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
+        if (r < 0) {
+            DPRINTF("husb: async. discard urb failed errno %d\n", errno);
+        }
     }
 }
 
@@ -692,7 +698,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         }
     }
 
-    usb_defer_packet(p, async_cancel, aurb);
+    usb_defer_packet(p, async_cancel, s);
     return USB_RET_ASYNC;
 }
 
@@ -823,7 +829,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
         }
     }
 
-    usb_defer_packet(p, async_cancel, aurb);
+    usb_defer_packet(p, async_cancel, s);
     return USB_RET_ASYNC;
 }
 
-- 
1.7.3.2