usb-hcd-xhci: Update endpoint context dequeue pointer for streams too

With streams the endpoint context dequeue pointer should point to the
dequeue value for the currently active stream.

At least Linux guests expect it to point to value set by an set_ep_dequeue
upon completion of the set_ep_dequeue (before kicking the ep).

Otherwise the Linux kernel will complain (and things won't work):

xhci_hcd 0000:00:05.0: Mismatch between completed Set TR Deq Ptr command & xHCI internal state.
xhci_hcd 0000:00:05.0: ep deq seg = ffff8800366f0880, deq ptr = ffff8800366ec010

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Hans de Goede 2013-10-08 21:58:12 +02:00 committed by Gerd Hoffmann
parent 582d6f4aba
commit c90daa1c10
1 changed files with 8 additions and 2 deletions

View File

@ -1187,6 +1187,7 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
XHCIStreamContext *sctx, uint32_t state) XHCIStreamContext *sctx, uint32_t state)
{ {
XHCIRing *ring = NULL;
uint32_t ctx[5]; uint32_t ctx[5];
uint32_t ctx2[2]; uint32_t ctx2[2];
@ -1197,6 +1198,7 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
/* update ring dequeue ptr */ /* update ring dequeue ptr */
if (epctx->nr_pstreams) { if (epctx->nr_pstreams) {
if (sctx != NULL) { if (sctx != NULL) {
ring = &sctx->ring;
xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2)); xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
ctx2[0] &= 0xe; ctx2[0] &= 0xe;
ctx2[0] |= sctx->ring.dequeue | sctx->ring.ccs; ctx2[0] |= sctx->ring.dequeue | sctx->ring.ccs;
@ -1204,8 +1206,12 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
xhci_dma_write_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2)); xhci_dma_write_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
} }
} else { } else {
ctx[2] = epctx->ring.dequeue | epctx->ring.ccs; ring = &epctx->ring;
ctx[3] = (epctx->ring.dequeue >> 16) >> 16; }
if (ring) {
ctx[2] = ring->dequeue | ring->ccs;
ctx[3] = (ring->dequeue >> 16) >> 16;
DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n", DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
epctx->pctx, state, ctx[3], ctx[2]); epctx->pctx, state, ctx[3], ctx[2]);
} }