958e1b
From 83423f42cd68e8b3ee644f38686dc4eabba9ce37 Mon Sep 17 00:00:00 2001
958e1b
From: Gerd Hoffmann <kraxel@redhat.com>
958e1b
Date: Fri, 11 Jul 2014 14:20:51 +0200
958e1b
Subject: [PATCH 17/43] usb-hcd-xhci: Update endpoint context dequeue pointer
958e1b
 for streams too
958e1b
958e1b
Message-id: <1405088470-24115-19-git-send-email-kraxel@redhat.com>
958e1b
Patchwork-id: 59838
958e1b
O-Subject: [RHEL-7.1 qemu-kvm PATCH 18/37] usb-hcd-xhci: Update endpoint context dequeue pointer for streams too
958e1b
Bugzilla: 980747
958e1b
RH-Acked-by: Dr. David Alan Gilbert (git) <dgilbert@redhat.com>
958e1b
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
958e1b
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
958e1b
958e1b
From: Hans de Goede <hdegoede@redhat.com>
958e1b
958e1b
With streams the endpoint context dequeue pointer should point to the
958e1b
dequeue value for the currently active stream.
958e1b
958e1b
At least Linux guests expect it to point to value set by an set_ep_dequeue
958e1b
upon completion of the set_ep_dequeue (before kicking the ep).
958e1b
958e1b
Otherwise the Linux kernel will complain (and things won't work):
958e1b
958e1b
xhci_hcd 0000:00:05.0: Mismatch between completed Set TR Deq Ptr command & xHCI internal state.
958e1b
xhci_hcd 0000:00:05.0: ep deq seg = ffff8800366f0880, deq ptr = ffff8800366ec010
958e1b
958e1b
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
958e1b
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
958e1b
(cherry picked from commit c90daa1c109348099088c1cc954c1e9f3392ae03)
958e1b
---
958e1b
 hw/usb/hcd-xhci.c | 10 ++++++++--
958e1b
 1 file changed, 8 insertions(+), 2 deletions(-)
958e1b
958e1b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
958e1b
---
958e1b
 hw/usb/hcd-xhci.c | 10 ++++++++--
958e1b
 1 file changed, 8 insertions(+), 2 deletions(-)
958e1b
958e1b
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
958e1b
index fc3b330..ef0c073 100644
958e1b
--- a/hw/usb/hcd-xhci.c
958e1b
+++ b/hw/usb/hcd-xhci.c
958e1b
@@ -1189,6 +1189,7 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
958e1b
 static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
958e1b
                               XHCIStreamContext *sctx, uint32_t state)
958e1b
 {
958e1b
+    XHCIRing *ring = NULL;
958e1b
     uint32_t ctx[5];
958e1b
     uint32_t ctx2[2];
958e1b
 
958e1b
@@ -1199,6 +1200,7 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
958e1b
     /* update ring dequeue ptr */
958e1b
     if (epctx->nr_pstreams) {
958e1b
         if (sctx != NULL) {
958e1b
+            ring = &sctx->ring;
958e1b
             xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
958e1b
             ctx2[0] &= 0xe;
958e1b
             ctx2[0] |= sctx->ring.dequeue | sctx->ring.ccs;
958e1b
@@ -1206,8 +1208,12 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
958e1b
             xhci_dma_write_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
958e1b
         }
958e1b
     } else {
958e1b
-        ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
958e1b
-        ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
958e1b
+        ring = &epctx->ring;
958e1b
+    }
958e1b
+    if (ring) {
958e1b
+        ctx[2] = ring->dequeue | ring->ccs;
958e1b
+        ctx[3] = (ring->dequeue >> 16) >> 16;
958e1b
+
958e1b
         DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
958e1b
                 epctx->pctx, state, ctx[3], ctx[2]);
958e1b
     }
958e1b
-- 
958e1b
1.8.3.1
958e1b