Blame 0130-Revert-ehci-don-t-flush-cache-on-doorbell-rings.patch

5544c1
From 4547897358a12c0f31d688da9922236984742242 Mon Sep 17 00:00:00 2001
c8dfc6
From: Hans de Goede <hdegoede@redhat.com>
c8dfc6
Date: Wed, 29 Aug 2012 10:12:52 +0200
5544c1
Subject: [PATCH] Revert "ehci: don't flush cache on doorbell rings."
c8dfc6
c8dfc6
This reverts commit 9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0, which got
c8dfc6
added to fix an issue where the real, underlying cause was not stopping
c8dfc6
the ep queue on an error.
c8dfc6
c8dfc6
Now that the underlying cause is fixed by the "usb: Halt ep queue and
c8dfc6
cancel pending packets on a packet error" patch, the "don't flush" fix
c8dfc6
is no longer needed.
c8dfc6
c8dfc6
Not only is it not needed, it causes us to see cancellations (unlinks)
c8dfc6
done by the Linux EHCI driver too late, which in combination with the new
c8dfc6
usb-core packet-id generation where qtd addresses are used as ids, causes
c8dfc6
duplicate ids for in flight packets.
c8dfc6
c8dfc6
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
5544c1
(cherry picked from commit 66f092d25697e11847b61d761c38ddebedaed8d1)
5544c1
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
c8dfc6
---
c8dfc6
 hw/usb/hcd-ehci.c | 35 ++++++-----------------------------
c8dfc6
 1 file changed, 6 insertions(+), 29 deletions(-)
c8dfc6
c8dfc6
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
c8dfc6
index 9523247..e7c36f4 100644
c8dfc6
--- a/hw/usb/hcd-ehci.c
c8dfc6
+++ b/hw/usb/hcd-ehci.c
c8dfc6
@@ -365,7 +365,6 @@ struct EHCIQueue {
c8dfc6
     uint32_t seen;
c8dfc6
     uint64_t ts;
c8dfc6
     int async;
c8dfc6
-    int revalidate;
c8dfc6
 
c8dfc6
     /* cached data from guest - needs to be flushed
c8dfc6
      * when guest removes an entry (doorbell, handshake sequence)
c8dfc6
@@ -805,18 +804,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
c8dfc6
     return NULL;
c8dfc6
 }
c8dfc6
 
c8dfc6
-static void ehci_queues_tag_unused_async(EHCIState *ehci)
c8dfc6
-{
c8dfc6
-    EHCIQueue *q;
c8dfc6
-
c8dfc6
-    QTAILQ_FOREACH(q, &ehci->aqueues, next) {
c8dfc6
-        if (!q->seen) {
c8dfc6
-            q->revalidate = 1;
c8dfc6
-        }
c8dfc6
-    }
c8dfc6
-}
c8dfc6
-
c8dfc6
-static void ehci_queues_rip_unused(EHCIState *ehci, int async)
c8dfc6
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
c8dfc6
 {
c8dfc6
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
c8dfc6
     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
c8dfc6
@@ -828,7 +816,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async)
c8dfc6
             q->ts = ehci->last_run_ns;
c8dfc6
             continue;
c8dfc6
         }
c8dfc6
-        if (ehci->last_run_ns < q->ts + maxage) {
c8dfc6
+        if (!flush && ehci->last_run_ns < q->ts + maxage) {
c8dfc6
             continue;
c8dfc6
         }
c8dfc6
         ehci_free_queue(q);
c8dfc6
@@ -1684,7 +1672,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
c8dfc6
         ehci_set_usbsts(ehci, USBSTS_REC);
c8dfc6
     }
c8dfc6
 
c8dfc6
-    ehci_queues_rip_unused(ehci, async);
c8dfc6
+    ehci_queues_rip_unused(ehci, async, 0);
c8dfc6
 
c8dfc6
     /*  Find the head of the list (4.9.1.1) */
c8dfc6
     for(i = 0; i < MAX_QH; i++) {
c8dfc6
@@ -1769,7 +1757,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
c8dfc6
     EHCIPacket *p;
c8dfc6
     uint32_t entry, devaddr;
c8dfc6
     EHCIQueue *q;
c8dfc6
-    EHCIqh qh;
c8dfc6
 
c8dfc6
     entry = ehci_get_fetch_addr(ehci, async);
c8dfc6
     q = ehci_find_queue_by_qh(ehci, entry, async);
c8dfc6
@@ -1787,17 +1774,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
c8dfc6
     }
c8dfc6
 
c8dfc6
     get_dwords(ehci, NLPTR_GET(q->qhaddr),
c8dfc6
-               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
c8dfc6
-    if (q->revalidate && (q->qh.epchar      != qh.epchar ||
c8dfc6
-                          q->qh.epcap       != qh.epcap  ||
c8dfc6
-                          q->qh.current_qtd != qh.current_qtd)) {
c8dfc6
-        ehci_free_queue(q);
c8dfc6
-        q = ehci_alloc_queue(ehci, entry, async);
c8dfc6
-        q->seen++;
c8dfc6
-        p = NULL;
c8dfc6
-    }
c8dfc6
-    q->qh = qh;
c8dfc6
-    q->revalidate = 0;
c8dfc6
+               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
c8dfc6
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
c8dfc6
 
c8dfc6
     devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
c8dfc6
@@ -2306,7 +2283,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
c8dfc6
          */
c8dfc6
         if (ehci->usbcmd & USBCMD_IAAD) {
c8dfc6
             /* Remove all unseen qhs from the async qhs queue */
c8dfc6
-            ehci_queues_tag_unused_async(ehci);
c8dfc6
+            ehci_queues_rip_unused(ehci, async, 1);
c8dfc6
             DPRINTF("ASYNC: doorbell request acknowledged\n");
c8dfc6
             ehci->usbcmd &= ~USBCMD_IAAD;
c8dfc6
             ehci_raise_irq(ehci, USBSTS_IAA);
c8dfc6
@@ -2359,7 +2336,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
c8dfc6
         ehci_set_fetch_addr(ehci, async,entry);
c8dfc6
         ehci_set_state(ehci, async, EST_FETCHENTRY);
c8dfc6
         ehci_advance_state(ehci, async);
c8dfc6
-        ehci_queues_rip_unused(ehci, async);
c8dfc6
+        ehci_queues_rip_unused(ehci, async, 0);
c8dfc6
         break;
c8dfc6
 
c8dfc6
     default:
c8dfc6
-- 
5544c1
1.7.12.1
c8dfc6