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

Hans de Goede c8dfc6
From 833eeda8129b2cf4955a34600b60c01e00652526 Mon Sep 17 00:00:00 2001
Hans de Goede c8dfc6
From: Hans de Goede <hdegoede@redhat.com>
Hans de Goede c8dfc6
Date: Wed, 5 Sep 2012 12:13:41 +0200
Hans de Goede c8dfc6
Subject: [PATCH 358/366] ehci: Don't set seen to 0 when removing unseen
Hans de Goede c8dfc6
 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>
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
Hans de Goede c8dfc6
index f5ba8e1..6f48132 100644
Hans de Goede c8dfc6
--- a/hw/usb/hcd-ehci.c
Hans de Goede c8dfc6
+++ b/hw/usb/hcd-ehci.c
Hans de Goede c8dfc6
@@ -847,10 +847,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
 
Hans de Goede c8dfc6
@@ -860,13 +860,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;
Hans de Goede c8dfc6
@@ -1699,7 +1711,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++) {
Hans de Goede c8dfc6
@@ -2331,7 +2343,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);
Hans de Goede c8dfc6
@@ -2384,7 +2396,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
-- 
Hans de Goede c8dfc6
1.7.12
Hans de Goede c8dfc6