Commit 53348b62 authored by Robert Sprowson's avatar Robert Sprowson

Fix for sending a stale TRB from a pipe that was previously open

Performing an open/out/close set of operations leaves the TRBs from the output step in the transfer ring for that endpoint. Subsequently re-opening the same endpoint a second time would start appending new TRBs on the end of the ring, but as the hardware's dequeue pointer gets reset to 0 all the old TRBs (with stale pointers to data) would get repeated.
Now, when an endpoint is configured (and hence the hardware's dequeue pointer set) the shadow copy in RAM is also cleared. Since this procedure is also needed during slot initialisation and stall clear, make it a function too.

Fixes problem with 1st print job from Printer Manager being good, and the 2nd print job being bad due to bits of the previous page being jumbled up in the data stream. Also fixes problem with TWAIN scanner failing to complete a scan, for the same reason. Endpoints that are only ever opened, such as mass storage devices, were not affected as the hardware's dequeue pointer always matched the software's copy.

From NetBSD revision 1.56, ref http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=51202.

Version 0.16. Tagged as 'XHCIDriver-0_16'
parent 505a8e65
/* (0.15)
/* (0.16)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.15
#define Module_MajorVersion_CMHG 0.16
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 06 Jun 2016
#define Module_MajorVersion "0.15"
#define Module_Version 15
#define Module_MajorVersion "0.16"
#define Module_Version 16
#define Module_MinorVersion ""
#define Module_Date "06 Jun 2016"
......@@ -18,6 +18,6 @@
#define Module_ComponentName "XHCIDriver"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/Controllers/XHCIDriver"
#define Module_FullVersion "0.15"
#define Module_HelpVersion "0.15 (06 Jun 2016)"
#define Module_LibraryVersionInfo "0:15"
#define Module_FullVersion "0.16"
#define Module_HelpVersion "0.16 (06 Jun 2016)"
#define Module_LibraryVersionInfo "0:16"
......@@ -168,6 +168,7 @@ static usbd_status xhci_unconfigure_endpoint(usbd_pipe_handle);
static usbd_status xhci_reset_endpoint(usbd_pipe_handle);
static usbd_status xhci_stop_endpoint(usbd_pipe_handle);
static void xhci_host_dequeue(struct xhci_ring * const);
static usbd_status xhci_set_dequeue(usbd_pipe_handle);
static usbd_status xhci_do_command(struct xhci_softc * const,
......@@ -1241,6 +1242,19 @@ xhci_stop_endpoint(usbd_pipe_handle pipe)
}
#endif
static void
xhci_host_dequeue(struct xhci_ring * const xr)
{
/* When dequeueing the controller, update our struct copy too */
memset(xr->xr_trb, 0, xr->xr_ntrb * XHCI_TRB_SIZE);
usb_syncmem(&xr->xr_dma, 0, xr->xr_ntrb * XHCI_TRB_SIZE,
BUS_DMASYNC_PREWRITE);
memset(xr->xr_cookies, 0, xr->xr_ntrb * sizeof(*xr->xr_cookies));
xr->xr_ep = 0;
xr->xr_cs = 1;
}
static usbd_status
xhci_set_dequeue(usbd_pipe_handle pipe)
{
......@@ -1254,15 +1268,7 @@ xhci_set_dequeue(usbd_pipe_handle pipe)
XHCIHIST_FUNC(); XHCIHIST_CALLED();
DPRINTFN(4, "slot %u dci %u", xs->xs_idx, dci, 0, 0);
memset(xr->xr_trb, 0, xr->xr_ntrb * XHCI_TRB_SIZE);
usb_syncmem(&xr->xr_dma, 0, xr->xr_ntrb * XHCI_TRB_SIZE,
BUS_DMASYNC_PREWRITE);
#ifdef BRANCH_NHUSB
memset(xr->xr_cookies, 0, xr->xr_ntrb * sizeof(*xr->xr_cookies));
#endif
xr->xr_ep = 0;
xr->xr_cs = 1;
xhci_host_dequeue(xr);
trb.trb_0 = xhci_ring_trbp(xr, 0) | 1; /* XXX */
trb.trb_2 = 0;
......@@ -1398,6 +1404,9 @@ xhci_close_pipe(usbd_pipe_handle pipe)
cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
cp[0] = htole32(XHCI_SCTX_0_CTX_NUM_SET(dci));
/* configure ep context performs an implicit dequeue */
xhci_host_dequeue(&xs->xs_ep[dci].xe_tr);
/* sync input contexts before they are read from memory */
usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE);
......@@ -2185,11 +2194,8 @@ xhci_ring_init(struct xhci_softc * const sc, struct xhci_ring * const xr,
xr->xr_cookies = kmem_zalloc(sizeof(*xr->xr_cookies) * ntrb, KM_SLEEP);
xr->xr_trb = xhci_ring_trbv(xr, 0);
xr->xr_ntrb = ntrb;
xr->xr_ep = 0;
xr->xr_cs = 1;
memset(xr->xr_trb, 0, size);
usb_syncmem(&xr->xr_dma, 0, size, BUS_DMASYNC_PREWRITE);
xr->is_halted = false;
xhci_host_dequeue(xr);
return USBD_NORMAL_COMPLETION;
}
......@@ -2647,6 +2653,7 @@ xhci_init_slot(struct xhci_softc * const sc, uint32_t slot, int depth,
XHCI_EPCTX_1_EPTYPE_SET(4) |
XHCI_EPCTX_1_CERR_SET(3)
);
/* rewind TR dequeue pointer in xHC */
/* can't use xhci_ep_get_dci() yet? */
*(uint64_t *)(&cp[2]) = htole64(
xhci_ring_trbp(&xs->xs_ep[XHCI_DCI_EP_CONTROL].xe_tr, 0) |
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment