From 946ff2c0c353e4bf493f6ff2bcc308adddee4a4c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 8 Oct 2013 21:58:09 +0200 Subject: usb-hcd-xhci: Remove unused sstreamsm member from XHCIStreamContext Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'hw/usb/hcd-xhci.c') diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 469c24d..e078c50 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -374,7 +374,6 @@ struct XHCIStreamContext { dma_addr_t pctx; unsigned int sct; XHCIRing ring; - XHCIStreamContext *sstreams; }; struct XHCIEPContext { @@ -1133,7 +1132,6 @@ static void xhci_reset_streams(XHCIEPContext *epctx) for (i = 0; i < epctx->nr_pstreams; i++) { epctx->pstreams[i].sct = -1; - g_free(epctx->pstreams[i].sstreams); } } @@ -1146,15 +1144,8 @@ static void xhci_alloc_streams(XHCIEPContext *epctx, dma_addr_t base) static void xhci_free_streams(XHCIEPContext *epctx) { - int i; - assert(epctx->pstreams != NULL); - if (!epctx->lsa) { - for (i = 0; i < epctx->nr_pstreams; i++) { - g_free(epctx->pstreams[i].sstreams); - } - } g_free(epctx->pstreams); epctx->pstreams = NULL; epctx->nr_pstreams = 0; -- cgit v1.1 From 8de1838afed4b5b05d18cc42a3e5a6fe9b19f29b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 8 Oct 2013 21:58:10 +0200 Subject: usb-hcd-xhci: Remove unused cancelled member from XHCITransfer Since qemu's USB model is geared towards emulated devices cancellation is instanteneous, so no need to wait for cancellation to complete, as such there is no wait for cancellation code, and the cancelled bool as well as the bogus comment about it can be removed. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'hw/usb/hcd-xhci.c') diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e078c50..7cf89ce 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -346,7 +346,6 @@ typedef struct XHCITransfer { QEMUSGList sgl; bool running_async; bool running_retry; - bool cancelled; bool complete; bool int_req; unsigned int iso_pkts; @@ -1310,8 +1309,6 @@ static int xhci_ep_nuke_one_xfer(XHCITransfer *t) if (t->running_async) { usb_cancel_packet(&t->packet); t->running_async = 0; - t->cancelled = 1; - DPRINTF("xhci: cancelling transfer, waiting for it to complete\n"); killed = 1; } if (t->running_retry) { @@ -1728,14 +1725,12 @@ static int xhci_complete_packet(XHCITransfer *xfer) xfer->running_async = 1; xfer->running_retry = 0; xfer->complete = 0; - xfer->cancelled = 0; return 0; } else if (xfer->packet.status == USB_RET_NAK) { trace_usb_xhci_xfer_nak(xfer); xfer->running_async = 0; xfer->running_retry = 1; xfer->complete = 0; - xfer->cancelled = 0; return 0; } else { xfer->running_async = 0; -- cgit v1.1 From 582d6f4aba0ff24604a82b48aee2db17b100d4b4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 8 Oct 2013 21:58:11 +0200 Subject: usb-hcd-xhci: Report completion of active transfer with CC_STOPPED on ep stop As we should per the XHCI spec "4.6.9 Stop Endpoint". Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'hw/usb/hcd-xhci.c') diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 7cf89ce..0131151 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -505,6 +505,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid, unsigned int streamid); static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); +static void xhci_xfer_report(XHCITransfer *xfer); static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v); static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v); static USBEndpoint *xhci_epid_to_usbep(XHCIState *xhci, @@ -1302,10 +1303,15 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, return CC_SUCCESS; } -static int xhci_ep_nuke_one_xfer(XHCITransfer *t) +static int xhci_ep_nuke_one_xfer(XHCITransfer *t, TRBCCode report) { int killed = 0; + if (report && (t->running_async || t->running_retry)) { + t->status = report; + xhci_xfer_report(t); + } + if (t->running_async) { usb_cancel_packet(&t->packet); t->running_async = 0; @@ -1318,6 +1324,7 @@ static int xhci_ep_nuke_one_xfer(XHCITransfer *t) timer_del(epctx->kick_timer); } t->running_retry = 0; + killed = 1; } if (t->trbs) { g_free(t->trbs); @@ -1330,7 +1337,7 @@ static int xhci_ep_nuke_one_xfer(XHCITransfer *t) } static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, - unsigned int epid) + unsigned int epid, TRBCCode report) { XHCISlot *slot; XHCIEPContext *epctx; @@ -1351,7 +1358,10 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, xferi = epctx->next_xfer; for (i = 0; i < TD_QUEUE; i++) { - killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi]); + killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi], report); + if (killed) { + report = 0; /* Only report once */ + } epctx->transfers[xferi].packet.ep = NULL; xferi = (xferi + 1) % TD_QUEUE; } @@ -1381,7 +1391,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, return CC_SUCCESS; } - xhci_ep_nuke_xfers(xhci, slotid, epid); + xhci_ep_nuke_xfers(xhci, slotid, epid, 0); epctx = slot->eps[epid-1]; @@ -1423,7 +1433,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid, return CC_EP_NOT_ENABLED_ERROR; } - if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) { + if (xhci_ep_nuke_xfers(xhci, slotid, epid, CC_STOPPED) > 0) { fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, " "data might be lost\n"); } @@ -1468,7 +1478,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, return CC_CONTEXT_STATE_ERROR; } - if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) { + if (xhci_ep_nuke_xfers(xhci, slotid, epid, 0) > 0) { fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, " "data might be lost\n"); } @@ -2461,7 +2471,7 @@ static void xhci_detach_slot(XHCIState *xhci, USBPort *uport) for (ep = 0; ep < 31; ep++) { if (xhci->slots[slot].eps[ep]) { - xhci_ep_nuke_xfers(xhci, slot+1, ep+1); + xhci_ep_nuke_xfers(xhci, slot + 1, ep + 1, 0); } } xhci->slots[slot].uport = NULL; @@ -3276,7 +3286,7 @@ static void xhci_complete(USBPort *port, USBPacket *packet) XHCITransfer *xfer = container_of(packet, XHCITransfer, packet); if (packet->status == USB_RET_REMOVE_FROM_QUEUE) { - xhci_ep_nuke_one_xfer(xfer); + xhci_ep_nuke_one_xfer(xfer, 0); return; } xhci_complete_packet(xfer); -- cgit v1.1 From c90daa1c109348099088c1cc954c1e9f3392ae03 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 8 Oct 2013 21:58:12 +0200 Subject: 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 Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'hw/usb/hcd-xhci.c') diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 0131151..fa27299 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1187,6 +1187,7 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx, static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, XHCIStreamContext *sctx, uint32_t state) { + XHCIRing *ring = NULL; uint32_t ctx[5]; uint32_t ctx2[2]; @@ -1197,6 +1198,7 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, /* update ring dequeue ptr */ if (epctx->nr_pstreams) { if (sctx != NULL) { + ring = &sctx->ring; xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2)); ctx2[0] &= 0xe; 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)); } } else { - ctx[2] = epctx->ring.dequeue | epctx->ring.ccs; - ctx[3] = (epctx->ring.dequeue >> 16) >> 16; + ring = &epctx->ring; + } + 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", epctx->pctx, state, ctx[3], ctx[2]); } -- cgit v1.1