Module Name: src Committed By: skrll Date: Sun Feb 28 09:16:20 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: ehci.c ohci.c uhci.c usbdi.c xhci.c src/sys/external/bsd/dwc2 [nick-nhusb]: dwc2.c Log Message: Centralise the up_repeat handling and use the standard pipe method to start the next transfer. This allows the removal of a bunch of code in the upm_done methods for interrupt transfers which had copies of the upm_start method code. At the same time we can perform the upm_done method before calling the transfer callback allowing correct bus_dma(9) operations before using the transfer DMA buffer. To generate a diff of this commit: cvs rdiff -u -r1.234.2.90 -r1.234.2.91 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.254.2.53 -r1.254.2.54 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.264.4.62 -r1.264.4.63 src/sys/dev/usb/uhci.c cvs rdiff -u -r1.162.2.42 -r1.162.2.43 src/sys/dev/usb/usbdi.c cvs rdiff -u -r1.28.2.52 -r1.28.2.53 src/sys/dev/usb/xhci.c cvs rdiff -u -r1.32.2.17 -r1.32.2.18 src/sys/external/bsd/dwc2/dwc2.c 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/ehci.c diff -u src/sys/dev/usb/ehci.c:1.234.2.90 src/sys/dev/usb/ehci.c:1.234.2.91 --- src/sys/dev/usb/ehci.c:1.234.2.90 Sat Feb 27 17:03:58 2016 +++ src/sys/dev/usb/ehci.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.234.2.90 2016/02/27 17:03:58 skrll Exp $ */ +/* $NetBSD: ehci.c,v 1.234.2.91 2016/02/28 09:16:20 skrll Exp $ */ /* * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.90 2016/02/27 17:03:58 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.91 2016/02/28 09:16:20 skrll Exp $"); #include "ohci.h" #include "uhci.h" @@ -838,11 +838,6 @@ ehci_softintr(void *v) * the _SAFE version of TAILQ_FOREACH. */ TAILQ_FOREACH_SAFE(ex, &cq, ex_next, nextex) { - /* - * XXX transfer_complete memcpys out transfer data (for in - * endpoints) during this call, before methods->done is called. - * A dma sync required beforehand. - */ usb_transfer_complete(&ex->ex_xfer); } @@ -4248,11 +4243,9 @@ ehci_device_intr_close(struct usbd_pipe Static void ehci_device_intr_done(struct usbd_xfer *xfer) { - ehci_softc_t *sc = EHCI_XFER2SC(xfer); - struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); + ehci_softc_t *sc __diagused = EHCI_XFER2SC(xfer); struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); - ehci_soft_qh_t *sqh; - int len, isread, endpt; + int isread, endpt; USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); @@ -4261,43 +4254,10 @@ ehci_device_intr_done(struct usbd_xfer * KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); - if (xfer->ux_pipe->up_repeat) { - - KASSERT(exfer->ex_isdone); -#ifdef DIAGNOSTIC - exfer->ex_isdone = false; -#endif - - len = xfer->ux_length; - endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - usb_syncmem(&xfer->ux_dmabuf, 0, len, - isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - sqh = epipe->sqh; - - ehci_soft_qtd_t *end; - ehci_reset_sqtd_chain(sc, xfer, len, isread, - &epipe->nexttoggle, &end); - end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); - usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - exfer->ex_sqtdend = end; - - /* also does usb_syncmem(sqh) */ - ehci_set_qh_qtd(sqh, exfer->ex_sqtdstart); - if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) { - callout_reset(&xfer->ux_callout, - mstohz(xfer->ux_timeout), ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->ux_status = USBD_IN_PROGRESS; - } else { - endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, - isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - } + endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; + isread = UE_GET_DIR(endpt) == UE_DIR_IN; + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, + isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } /************************/ Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.254.2.53 src/sys/dev/usb/ohci.c:1.254.2.54 --- src/sys/dev/usb/ohci.c:1.254.2.53 Sat Feb 27 15:54:30 2016 +++ src/sys/dev/usb/ohci.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.254.2.53 2016/02/27 15:54:30 skrll Exp $ */ +/* $NetBSD: ohci.c,v 1.254.2.54 2016/02/28 09:16:20 skrll Exp $ */ /* * Copyright (c) 1998, 2004, 2005, 2012 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.254.2.53 2016/02/27 15:54:30 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.254.2.54 2016/02/28 09:16:20 skrll Exp $"); #include "opt_usb.h" @@ -1679,10 +1679,7 @@ ohci_device_ctrl_done(struct usbd_xfer * void ohci_device_intr_done(struct usbd_xfer *xfer) { - struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); - struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); - ohci_softc_t *sc = OHCI_XFER2SC(xfer); - ohci_soft_ed_t *sed = opipe->sed; + ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); int isread = (UE_GET_DIR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN); @@ -1693,47 +1690,6 @@ ohci_device_intr_done(struct usbd_xfer * usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - if (xfer->ux_pipe->up_repeat) { - ohci_soft_td_t *data, *last, *tail; - int len = xfer->ux_length; - - /* - * Use the pipe "tail" TD as our first and loan our first TD - * to the next transfer. - */ - data = opipe->tail.td; - opipe->tail.td = ox->ox_stds[0]; - ox->ox_stds[0] = data; - ohci_reset_std_chain(sc, xfer, len, isread, data, &last); - - /* point at sentinel */ - tail = opipe->tail.td; - memset(&tail->td, 0, sizeof(tail->td)); - tail->nexttd = NULL; - tail->xfer = NULL; - usb_syncmem(&tail->dma, tail->offs, sizeof(tail->td), - BUS_DMASYNC_PREWRITE); - - /* We want interrupt at the end of the transfer. */ - last->td.td_flags &= HTOO32(~OHCI_TD_INTR_MASK); - last->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1)); - - last->td.td_nexttd = HTOO32(tail->physaddr); - last->nexttd = tail; - last->flags |= OHCI_CALL_DONE; - usb_syncmem(&last->dma, last->offs, sizeof(last->td), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - xfer->ux_hcpriv = data; - xfer->ux_actlen = 0; - - /* Insert ED in schedule */ - sed->ed.ed_tailp = HTOO32(tail->physaddr); - usb_syncmem(&sed->dma, - sed->offs + offsetof(ohci_ed_t, ed_tailp), - sizeof(sed->ed.ed_tailp), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - } } void @@ -1803,6 +1759,12 @@ ohci_rhsc(ohci_softc_t *sc, struct usbd_ void ohci_root_intr_done(struct usbd_xfer *xfer) { + ohci_softc_t *sc = OHCI_XFER2SC(xfer); + + KASSERT(mutex_owned(&sc->sc_lock)); + + KASSERT(sc->sc_intrxfer == xfer); + sc->sc_intrxfer = NULL; } /* Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.264.4.62 src/sys/dev/usb/uhci.c:1.264.4.63 --- src/sys/dev/usb/uhci.c:1.264.4.62 Sat Feb 27 16:07:01 2016 +++ src/sys/dev/usb/uhci.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.264.4.62 2016/02/27 16:07:01 skrll Exp $ */ +/* $NetBSD: uhci.c,v 1.264.4.63 2016/02/28 09:16:20 skrll Exp $ */ /* * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.264.4.62 2016/02/27 16:07:01 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.264.4.63 2016/02/28 09:16:20 skrll Exp $"); #include "opt_usb.h" @@ -3399,7 +3399,6 @@ void uhci_device_intr_done(struct usbd_xfer *xfer) { uhci_softc_t *sc = UHCI_XFER2SC(xfer); - struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); uhci_soft_qh_t *sqh; int i, npoll; @@ -3419,49 +3418,10 @@ uhci_device_intr_done(struct usbd_xfer * sizeof(sqh->qh.qh_elink), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); } - - if (xfer->ux_pipe->up_repeat) { - uhci_soft_td_t *data, *dataend; - int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; - int isread = UE_GET_DIR(endpt) == UE_DIR_IN; - - KASSERT(ux->ux_isdone); -#ifdef DIAGNOSTIC - ux->ux_isdone = false; -#endif - DPRINTFN(5, "re-queueing", 0, 0, 0, 0); - - data = ux->ux_stdstart; - uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread, - &upipe->nexttoggle, &dataend); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - usb_syncmem(&dataend->dma, - dataend->offs + offsetof(uhci_td_t, td_status), - sizeof(dataend->td.td_status), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - -#ifdef UHCI_DEBUG - if (uhcidebug >= 10) { - DPRINTF("--- dump start ---", 0, 0, 0, 0); - uhci_dump_tds(data); - uhci_dump_qh(upipe->intr.qhs[0]); - DPRINTF("--- dump end ---", 0, 0, 0, 0); - } -#endif - - ux->ux_stdend = dataend; - for (i = 0; i < npoll; i++) { - sqh = upipe->intr.qhs[i]; - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - usb_syncmem(&sqh->dma, - sqh->offs + offsetof(uhci_qh_t, qh_elink), - sizeof(sqh->qh.qh_elink), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - } - xfer->ux_status = USBD_IN_PROGRESS; - uhci_add_intr_list(sc, ux); - } + const int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; + const bool isread = UE_GET_DIR(endpt) == UE_DIR_IN; + usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, + isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } /* Deallocate request data structures */ Index: src/sys/dev/usb/usbdi.c diff -u src/sys/dev/usb/usbdi.c:1.162.2.42 src/sys/dev/usb/usbdi.c:1.162.2.43 --- src/sys/dev/usb/usbdi.c:1.162.2.42 Sun Feb 7 15:50:43 2016 +++ src/sys/dev/usb/usbdi.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.162.2.42 2016/02/07 15:50:43 skrll Exp $ */ +/* $NetBSD: usbdi.c,v 1.162.2.43 2016/02/28 09:16:20 skrll Exp $ */ /* * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.162.2.42 2016/02/07 15:50:43 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.162.2.43 2016/02/28 09:16:20 skrll Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -893,10 +893,11 @@ usb_transfer_complete(struct usbd_xfer * struct usbd_pipe *pipe = xfer->ux_pipe; struct usbd_bus *bus = pipe->up_dev->ud_bus; int sync = xfer->ux_flags & USBD_SYNCHRONOUS; - int erred = xfer->ux_status == USBD_CANCELLED || + int erred = + xfer->ux_status == USBD_CANCELLED || xfer->ux_status == USBD_TIMEOUT; int polling = bus->ub_usepolling; - int repeat; + int repeat = pipe->up_repeat; USBHIST_FUNC(); USBHIST_CALLED(usbdebug); @@ -907,21 +908,10 @@ usb_transfer_complete(struct usbd_xfer * KASSERT(xfer->ux_state == XFER_ONQU); KASSERT(pipe != NULL); - repeat = pipe->up_repeat; /* XXXX */ if (polling) pipe->up_running = 0; - if (xfer->ux_length != 0 && xfer->ux_buffer != xfer->ux_buf) { - KDASSERTMSG(xfer->ux_actlen <= xfer->ux_length, - "actlen %d length %d",xfer->ux_actlen, xfer->ux_length); - - /* Only if IN transfer */ - if (usbd_xfer_isread(xfer)) { - memcpy(xfer->ux_buffer, xfer->ux_buf, xfer->ux_actlen); - } - } - if (!repeat) { /* Remove request from queue. */ @@ -952,58 +942,54 @@ usb_transfer_complete(struct usbd_xfer * xfer->ux_status = USBD_SHORT_XFER; } - if (repeat) { - USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x", - xfer, xfer->ux_callback, xfer->ux_status, 0); - if (xfer->ux_callback) { - if (!polling) - mutex_exit(pipe->up_dev->ud_bus->ub_lock); - - if (!(pipe->up_flags & USBD_MPSAFE)) - KERNEL_LOCK(1, curlwp); - xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status); - USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer, - pipe->up_methods->upm_done, 0, 0); - if (!(pipe->up_flags & USBD_MPSAFE)) - KERNEL_UNLOCK_ONE(curlwp); + USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer, + pipe->up_methods->upm_done, 0, 0); + pipe->up_methods->upm_done(xfer); - if (!polling) - mutex_enter(pipe->up_dev->ud_bus->ub_lock); - } - pipe->up_methods->upm_done(xfer); - } else { - USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer, - pipe->up_methods->upm_done, 0, 0); - pipe->up_methods->upm_done(xfer); - USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x", - xfer, xfer->ux_callback, xfer->ux_status, 0); - if (xfer->ux_callback) { - if (!polling) - mutex_exit(pipe->up_dev->ud_bus->ub_lock); - - if (!(pipe->up_flags & USBD_MPSAFE)) - KERNEL_LOCK(1, curlwp); - xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status); - if (!(pipe->up_flags & USBD_MPSAFE)) - KERNEL_UNLOCK_ONE(curlwp); + if (xfer->ux_length != 0 && xfer->ux_buffer != xfer->ux_buf) { + KDASSERTMSG(xfer->ux_actlen <= xfer->ux_length, + "actlen %d length %d",xfer->ux_actlen, xfer->ux_length); - if (!polling) - mutex_enter(pipe->up_dev->ud_bus->ub_lock); + /* Only if IN transfer */ + if (usbd_xfer_isread(xfer)) { + memcpy(xfer->ux_buffer, xfer->ux_buf, xfer->ux_actlen); } } + USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %d", + xfer, xfer->ux_callback, xfer->ux_status, 0); + + if (xfer->ux_callback) { + if (!polling) + mutex_exit(pipe->up_dev->ud_bus->ub_lock); + + if (!(pipe->up_flags & USBD_MPSAFE)) + KERNEL_LOCK(1, curlwp); + + xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status); + + if (!(pipe->up_flags & USBD_MPSAFE)) + KERNEL_UNLOCK_ONE(curlwp); + + if (!polling) + mutex_enter(pipe->up_dev->ud_bus->ub_lock); + } + if (sync && !polling) { USBHIST_LOG(usbdebug, "<- done xfer %p, wakeup", xfer, 0, 0, 0); cv_broadcast(&xfer->ux_cv); } - if (!repeat) { + if (repeat) { + xfer->ux_actlen = 0; + xfer->ux_status = USBD_NOT_STARTED; + } else { /* XXX should we stop the queue on all errors? */ if (erred && pipe->up_iface != NULL) /* not control pipe */ pipe->up_running = 0; - else - usbd_start_next(pipe); } + if (pipe->up_running) + usbd_start_next(pipe); } /* Called with USB lock held. */ Index: src/sys/dev/usb/xhci.c diff -u src/sys/dev/usb/xhci.c:1.28.2.52 src/sys/dev/usb/xhci.c:1.28.2.53 --- src/sys/dev/usb/xhci.c:1.28.2.52 Sat Feb 13 09:33:12 2016 +++ src/sys/dev/usb/xhci.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: xhci.c,v 1.28.2.52 2016/02/13 09:33:12 skrll Exp $ */ +/* $NetBSD: xhci.c,v 1.28.2.53 2016/02/28 09:16:20 skrll Exp $ */ /* * Copyright (c) 2013 Jonathan A. Kollasch @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.52 2016/02/13 09:33:12 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.53 2016/02/28 09:16:20 skrll Exp $"); #include "opt_usb.h" @@ -3264,7 +3264,13 @@ static void xhci_device_ctrl_done(struct usbd_xfer *xfer) { XHCIHIST_FUNC(); XHCIHIST_CALLED(); - + usb_device_request_t *req = &xfer->ux_request; + int len = UGETW(req->wLength); + int rd = req->bmRequestType & UT_READ; + + if (len) + usb_syncmem(&xfer->ux_dmabuf, 0, len, + rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } static void @@ -3512,9 +3518,6 @@ xhci_device_intr_done(struct usbd_xfer * printf("\n"); #endif - if (xfer->ux_pipe->up_repeat) { - xfer->ux_status = xhci_device_intr_start(xfer); - } } static void Index: src/sys/external/bsd/dwc2/dwc2.c diff -u src/sys/external/bsd/dwc2/dwc2.c:1.32.2.17 src/sys/external/bsd/dwc2/dwc2.c:1.32.2.18 --- src/sys/external/bsd/dwc2/dwc2.c:1.32.2.17 Sun Dec 27 12:10:03 2015 +++ src/sys/external/bsd/dwc2/dwc2.c Sun Feb 28 09:16:20 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: dwc2.c,v 1.32.2.17 2015/12/27 12:10:03 skrll Exp $ */ +/* $NetBSD: dwc2.c,v 1.32.2.18 2016/02/28 09:16:20 skrll Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.32.2.17 2015/12/27 12:10:03 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.32.2.18 2016/02/28 09:16:20 skrll Exp $"); #include "opt_usb.h" @@ -911,11 +911,6 @@ dwc2_device_intr_done(struct usbd_xfer * { DPRINTF("\n"); - - if (xfer->ux_pipe->up_repeat) { - xfer->ux_status = USBD_IN_PROGRESS; - dwc2_device_start(xfer); - } } /***********************************************************************/