Module Name: src Committed By: skrll Date: Mon May 30 06:48:46 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: xhci.c xhcivar.h Log Message: Serialise commands To generate a diff of this commit: cvs rdiff -u -r1.28.2.69 -r1.28.2.70 src/sys/dev/usb/xhci.c cvs rdiff -u -r1.4.12.10 -r1.4.12.11 src/sys/dev/usb/xhcivar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/xhci.c diff -u src/sys/dev/usb/xhci.c:1.28.2.69 src/sys/dev/usb/xhci.c:1.28.2.70 --- src/sys/dev/usb/xhci.c:1.28.2.69 Sun May 29 08:44:31 2016 +++ src/sys/dev/usb/xhci.c Mon May 30 06:48:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: xhci.c,v 1.28.2.69 2016/05/29 08:44:31 skrll Exp $ */ +/* $NetBSD: xhci.c,v 1.28.2.70 2016/05/30 06:48:46 skrll Exp $ */ /* * Copyright (c) 2013 Jonathan A. Kollasch @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.69 2016/05/29 08:44:31 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.70 2016/05/30 06:48:46 skrll Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1017,6 +1017,7 @@ xhci_init(struct xhci_softc *sc) } cv_init(&sc->sc_command_cv, "xhcicmd"); + cv_init(&sc->sc_cmdbusy_cv, "xhcicmdq"); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); cv_init(&sc->sc_softwake_cv, "xhciab"); @@ -2024,11 +2025,15 @@ xhci_event_cmd(struct xhci_softc * const XHCIHIST_FUNC(); XHCIHIST_CALLED(); + KASSERT(mutex_owned(&sc->sc_lock)); + trb_0 = le64toh(trb->trb_0); trb_2 = le32toh(trb->trb_2); trb_3 = le32toh(trb->trb_3); if (trb_0 == sc->sc_command_addr) { + sc->sc_resultpending = false; + sc->sc_result_trb.trb_0 = trb_0; sc->sc_result_trb.trb_2 = trb_2; sc->sc_result_trb.trb_3 = trb_3; @@ -2633,9 +2638,11 @@ xhci_do_command_locked(struct xhci_softc KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); KASSERT(mutex_owned(&sc->sc_lock)); - /* XXX KASSERT may fire when cv_timedwait unlocks sc_lock */ - KASSERT(sc->sc_command_addr == 0); + while (sc->sc_command_addr != 0) + cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); + sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); + sc->sc_resultpending = true; mutex_enter(&cr->xr_lock); xhci_ring_put(sc, cr, NULL, trb, 1); @@ -2643,11 +2650,13 @@ xhci_do_command_locked(struct xhci_softc xhci_db_write_4(sc, XHCI_DOORBELL(0), 0); - if (cv_timedwait(&sc->sc_command_cv, &sc->sc_lock, - MAX(1, mstohz(timeout))) == EWOULDBLOCK) { - xhci_abort_command(sc); - err = USBD_TIMEOUT; - goto timedout; + while (sc->sc_resultpending) { + if (cv_timedwait(&sc->sc_command_cv, &sc->sc_lock, + MAX(1, mstohz(timeout))) == EWOULDBLOCK) { + xhci_abort_command(sc); + err = USBD_TIMEOUT; + goto timedout; + } } trb->trb_0 = sc->sc_result_trb.trb_0; @@ -2671,7 +2680,10 @@ xhci_do_command_locked(struct xhci_softc } timedout: + sc->sc_resultpending = false; sc->sc_command_addr = 0; + cv_broadcast(&sc->sc_cmdbusy_cv); + return err; } Index: src/sys/dev/usb/xhcivar.h diff -u src/sys/dev/usb/xhcivar.h:1.4.12.10 src/sys/dev/usb/xhcivar.h:1.4.12.11 --- src/sys/dev/usb/xhcivar.h:1.4.12.10 Sun May 29 08:44:31 2016 +++ src/sys/dev/usb/xhcivar.h Mon May 30 06:48:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: xhcivar.h,v 1.4.12.10 2016/05/29 08:44:31 skrll Exp $ */ +/* $NetBSD: xhcivar.h,v 1.4.12.11 2016/05/30 06:48:46 skrll Exp $ */ /* * Copyright (c) 2013 Jonathan A. Kollasch @@ -113,9 +113,11 @@ struct xhci_softc { usb_dma_t sc_spbufarray_dma; usb_dma_t *sc_spbuf_dma; + kcondvar_t sc_cmdbusy_cv; kcondvar_t sc_command_cv; bus_addr_t sc_command_addr; struct xhci_trb sc_result_trb; + bool sc_resultpending; bool sc_ac64; bool sc_dying;