carlwgeorge / rpms / qemu

Forked from rpms/qemu a year ago
Clone
5544c1b
From c7251f2557d09ce4b8466eeccd0f3264c297c515 Mon Sep 17 00:00:00 2001
c8dfc65
From: Hans de Goede <hdegoede@redhat.com>
c8dfc65
Date: Thu, 30 Aug 2012 15:18:24 +0200
5544c1b
Subject: [PATCH] ehci: Properly report completed but not yet processed
5544c1b
 packets to the guest
c8dfc65
c8dfc65
Reported packets which have completed before being cancelled as such to the
c8dfc65
host. Note that the new code path this patch adds is untested since it I've
c8dfc65
been unable to actually trigger the race which needs this code path.
c8dfc65
c8dfc65
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
5544c1b
(cherry picked from commit 4b63a0df3bda8a2c278e45d9d94d9ba6d5791d8d)
5544c1b
5544c1b
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
c8dfc65
---
c8dfc65
 hw/usb/hcd-ehci.c | 13 +++++++++++++
c8dfc65
 1 file changed, 13 insertions(+)
c8dfc65
c8dfc65
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
c8dfc65
index 4fe85c8..0a6c9ef 100644
c8dfc65
--- a/hw/usb/hcd-ehci.c
c8dfc65
+++ b/hw/usb/hcd-ehci.c
c8dfc65
@@ -489,6 +489,9 @@ static const char *ehci_mmio_names[] = {
c8dfc65
     [CONFIGFLAG]        = "CONFIGFLAG",
c8dfc65
 };
c8dfc65
 
c8dfc65
+static int ehci_state_executing(EHCIQueue *q);
c8dfc65
+static int ehci_state_writeback(EHCIQueue *q);
c8dfc65
+
c8dfc65
 static const char *nr2str(const char **n, size_t len, uint32_t nr)
c8dfc65
 {
c8dfc65
     if (nr < len && n[nr] != NULL) {
c8dfc65
@@ -750,6 +753,16 @@ static void ehci_free_packet(EHCIPacket *p)
c8dfc65
         usb_packet_unmap(&p->packet, &p->sgl);
c8dfc65
         qemu_sglist_destroy(&p->sgl);
c8dfc65
     }
c8dfc65
+    if (p->async == EHCI_ASYNC_FINISHED) {
c8dfc65
+        int state = ehci_get_state(p->queue->ehci, p->queue->async);
c8dfc65
+        /* This is a normal, but rare condition (cancel racing completion) */
c8dfc65
+        fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
c8dfc65
+        ehci_state_executing(p->queue);
c8dfc65
+        ehci_state_writeback(p->queue);
c8dfc65
+        ehci_set_state(p->queue->ehci, p->queue->async, state);
c8dfc65
+        /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
c8dfc65
+        return;
c8dfc65
+    }
c8dfc65
     QTAILQ_REMOVE(&p->queue->packets, p, next);
c8dfc65
     usb_packet_cleanup(&p->packet);
c8dfc65
     g_free(p);
c8dfc65
-- 
5544c1b
1.7.12.1
c8dfc65