Blame 0171-ehci-Don-t-set-seen-to-0-when-removing-unseen-queue-.patch

5544c1
From ade9c6dfbbf573c22800d7ff6df7f0de933e7c96 Mon Sep 17 00:00:00 2001
Hans de Goede c8dfc6
From: Hans de Goede <hdegoede@redhat.com>
5544c1
Date: Wed, 12 Sep 2012 15:08:32 +0200
5544c1
Subject: [PATCH] ehci: Don't set seen to 0 when removing unseen queue-heads
Hans de Goede c8dfc6
Hans de Goede c8dfc6
When removing unseen queue-heads from the async queue list, we should not
Hans de Goede c8dfc6
set the seen flag to 0, as this may cause them to be removed by
Hans de Goede c8dfc6
ehci_queues_rip_unused() during the next call to ehci_advance_async_state()
Hans de Goede c8dfc6
if the timer is late or running at a low frequency.
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Note:
Hans de Goede c8dfc6
1) This *may* have caused the instant unlink / relinks described in commit
Hans de Goede c8dfc6
   9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0
Hans de Goede c8dfc6
Hans de Goede c8dfc6
2) Rather then putting more if-s inside ehci_queues_rip_unused, this patch
Hans de Goede c8dfc6
   instead introduces a new ehci_queues_rip_unseen function.
Hans de Goede c8dfc6
Hans de Goede c8dfc6
3) This patch also makes it save to call ehci_queues_rip_unseen() multiple
Hans de Goede c8dfc6
   times, which gets used in the folluw up patch titled:
Hans de Goede c8dfc6
   "ehci: Walk async schedule before and after migration"
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
5544c1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
5544c1
(cherry picked from commit 8f5457eb04140714eaf57a99bc08dc661d83fa87)
5544c1
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Hans de Goede c8dfc6
---
Hans de Goede c8dfc6
 hw/usb/hcd-ehci.c | 24 ++++++++++++++++++------
Hans de Goede c8dfc6
 1 file changed, 18 insertions(+), 6 deletions(-)
Hans de Goede c8dfc6
Hans de Goede c8dfc6
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
5544c1
index 017a01d..bc86460 100644
Hans de Goede c8dfc6
--- a/hw/usb/hcd-ehci.c
Hans de Goede c8dfc6
+++ b/hw/usb/hcd-ehci.c
5544c1
@@ -848,10 +848,10 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
Hans de Goede c8dfc6
     return NULL;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
Hans de Goede c8dfc6
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
Hans de Goede c8dfc6
-    const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL;
Hans de Goede c8dfc6
+    const char *warn = async ? "guest unlinked busy QH" : NULL;
Hans de Goede c8dfc6
     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
Hans de Goede c8dfc6
     EHCIQueue *q, *tmp;
Hans de Goede c8dfc6
 
5544c1
@@ -861,13 +861,25 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
Hans de Goede c8dfc6
             q->ts = ehci->last_run_ns;
Hans de Goede c8dfc6
             continue;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
-        if (!flush && ehci->last_run_ns < q->ts + maxage) {
Hans de Goede c8dfc6
+        if (ehci->last_run_ns < q->ts + maxage) {
Hans de Goede c8dfc6
             continue;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
         ehci_free_queue(q, warn);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+static void ehci_queues_rip_unseen(EHCIState *ehci, int async)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
Hans de Goede c8dfc6
+    EHCIQueue *q, *tmp;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
Hans de Goede c8dfc6
+        if (!q->seen) {
Hans de Goede c8dfc6
+            ehci_free_queue(q, NULL);
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
5544c1
@@ -1700,7 +1712,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
Hans de Goede c8dfc6
         ehci_set_usbsts(ehci, USBSTS_REC);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    ehci_queues_rip_unused(ehci, async, 0);
Hans de Goede c8dfc6
+    ehci_queues_rip_unused(ehci, async);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /*  Find the head of the list (4.9.1.1) */
Hans de Goede c8dfc6
     for(i = 0; i < MAX_QH; i++) {
5544c1
@@ -2332,7 +2344,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
Hans de Goede c8dfc6
          */
Hans de Goede c8dfc6
         if (ehci->usbcmd & USBCMD_IAAD) {
Hans de Goede c8dfc6
             /* Remove all unseen qhs from the async qhs queue */
Hans de Goede c8dfc6
-            ehci_queues_rip_unused(ehci, async, 1);
Hans de Goede c8dfc6
+            ehci_queues_rip_unseen(ehci, async);
Hans de Goede c8dfc6
             trace_usb_ehci_doorbell_ack();
Hans de Goede c8dfc6
             ehci->usbcmd &= ~USBCMD_IAAD;
Hans de Goede c8dfc6
             ehci_raise_irq(ehci, USBSTS_IAA);
5544c1
@@ -2385,7 +2397,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
Hans de Goede c8dfc6
         ehci_set_fetch_addr(ehci, async,entry);
Hans de Goede c8dfc6
         ehci_set_state(ehci, async, EST_FETCHENTRY);
Hans de Goede c8dfc6
         ehci_advance_state(ehci, async);
Hans de Goede c8dfc6
-        ehci_queues_rip_unused(ehci, async, 0);
Hans de Goede c8dfc6
+        ehci_queues_rip_unused(ehci, async);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     default:
Hans de Goede c8dfc6
-- 
5544c1
1.7.12.1
Hans de Goede c8dfc6