Module Name: src Committed By: skrll Date: Thu Mar 17 09:04:53 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: ehci.c ehcivar.h ohci.c uhci.c uhcivar.h usbdi.c usbdivar.h src/sys/external/bsd/dwc2 [nick-nhusb]: dwc2.c Log Message: All HCDs were fighting the seriaisation of transfers in usbdi.c for isoc transfers. Instead allow the HCDs to specify which pipes can handle removing this serialisation and apply it appropriately. dwctwo(4) can handle this for all transfer types, but only enable bulk/isoc for now. To generate a diff of this commit: cvs rdiff -u -r1.234.2.91 -r1.234.2.92 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.42.14.22 -r1.42.14.23 src/sys/dev/usb/ehcivar.h cvs rdiff -u -r1.254.2.58 -r1.254.2.59 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.264.4.67 -r1.264.4.68 src/sys/dev/usb/uhci.c cvs rdiff -u -r1.52.14.16 -r1.52.14.17 src/sys/dev/usb/uhcivar.h cvs rdiff -u -r1.162.2.43 -r1.162.2.44 src/sys/dev/usb/usbdi.c cvs rdiff -u -r1.109.2.24 -r1.109.2.25 src/sys/dev/usb/usbdivar.h cvs rdiff -u -r1.32.2.23 -r1.32.2.24 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.91 src/sys/dev/usb/ehci.c:1.234.2.92 --- src/sys/dev/usb/ehci.c:1.234.2.91 Sun Feb 28 09:16:20 2016 +++ src/sys/dev/usb/ehci.c Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.234.2.91 2016/02/28 09:16:20 skrll Exp $ */ +/* $NetBSD: ehci.c,v 1.234.2.92 2016/03/17 09:04:53 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.91 2016/02/28 09:16:20 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.92 2016/03/17 09:04:53 skrll Exp $"); #include "ohci.h" #include "uhci.h" @@ -209,7 +209,6 @@ Static void ehci_device_intr_done(struc Static int ehci_device_isoc_init(struct usbd_xfer *); Static void ehci_device_isoc_fini(struct usbd_xfer *); Static usbd_status ehci_device_isoc_transfer(struct usbd_xfer *); -Static usbd_status ehci_device_isoc_start(struct usbd_xfer *); Static void ehci_device_isoc_abort(struct usbd_xfer *); Static void ehci_device_isoc_close(struct usbd_pipe *); Static void ehci_device_isoc_done(struct usbd_xfer *); @@ -217,7 +216,6 @@ Static void ehci_device_isoc_done(struc Static int ehci_device_fs_isoc_init(struct usbd_xfer *); Static void ehci_device_fs_isoc_fini(struct usbd_xfer *); Static usbd_status ehci_device_fs_isoc_transfer(struct usbd_xfer *); -Static usbd_status ehci_device_fs_isoc_start(struct usbd_xfer *); Static void ehci_device_fs_isoc_abort(struct usbd_xfer *); Static void ehci_device_fs_isoc_close(struct usbd_pipe *); Static void ehci_device_fs_isoc_done(struct usbd_xfer *); @@ -366,7 +364,6 @@ Static const struct usbd_pipe_methods eh .upm_init = ehci_device_isoc_init, .upm_fini = ehci_device_isoc_fini, .upm_transfer = ehci_device_isoc_transfer, - .upm_start = ehci_device_isoc_start, .upm_abort = ehci_device_isoc_abort, .upm_close = ehci_device_isoc_close, .upm_cleartoggle = ehci_noop, @@ -377,7 +374,6 @@ Static const struct usbd_pipe_methods eh .upm_init = ehci_device_fs_isoc_init, .upm_fini = ehci_device_fs_isoc_fini, .upm_transfer = ehci_device_fs_isoc_transfer, - .upm_start = ehci_device_fs_isoc_start, .upm_abort = ehci_device_fs_isoc_abort, .upm_close = ehci_device_fs_isoc_close, .upm_cleartoggle = ehci_noop, @@ -2066,6 +2062,7 @@ ehci_open(struct usbd_pipe *pipe) goto bad; break; case UE_ISOCHRONOUS: + pipe->up_serialise = false; if (speed == EHCI_QH_SPEED_HIGH) pipe->up_methods = &ehci_device_isoc_methods; else @@ -4368,22 +4365,14 @@ Static usbd_status ehci_device_fs_isoc_transfer(struct usbd_xfer *xfer) { ehci_softc_t *sc = EHCI_XFER2SC(xfer); - usbd_status err; + usbd_status __diagused err; mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); - if (err && err != USBD_IN_PROGRESS) - return err; - - return ehci_device_fs_isoc_start(xfer); -} + KASSERT(err == USBD_NORMAL_COMPLETION); -Static usbd_status -ehci_device_fs_isoc_start(struct usbd_xfer *xfer) -{ - ehci_softc_t *sc = EHCI_XFER2SC(xfer); struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer);; struct usbd_device *dev = xfer->ux_pipe->up_dev;; struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); @@ -4399,16 +4388,6 @@ ehci_device_fs_isoc_start(struct usbd_xf sitd = NULL; total_length = 0; - /* - * To allow continuous transfers, above we start all transfers - * immediately. However, we're still going to get usbd_start_next call - * this when another xfer completes. So, check if this is already - * in progress or not - */ - - if (exfer->ex_isrunning) { - return USBD_IN_PROGRESS; - } USBHIST_LOG(ehcidebug, "xfer %p len %d flags %d", xfer, xfer->ux_length, xfer->ux_flags, 0); @@ -4604,8 +4583,6 @@ ehci_device_fs_isoc_start(struct usbd_xf epipe->isoc.cur_xfers++; epipe->isoc.next_frame = frindex; - exfer->ex_isrunning = true; - ehci_add_intr_list(sc, exfer); xfer->ux_status = USBD_IN_PROGRESS; @@ -4646,10 +4623,7 @@ ehci_device_fs_isoc_done(struct usbd_xfe KASSERT(mutex_owned(&sc->sc_lock)); epipe->isoc.cur_xfers--; - if (exfer->ex_isrunning) { - ehci_remove_sitd_chain(sc, exfer->ex_itdstart); - exfer->ex_isrunning = false; - } + ehci_remove_sitd_chain(sc, exfer->ex_itdstart); usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); @@ -4681,7 +4655,6 @@ ehci_device_isoc_init(struct usbd_xfer * KASSERT(exfer->ex_isdone); exfer->ex_type = EX_ISOC; - exfer->ex_isrunning = false; /* * Step 1: Allocate and initialize itds, how many do we need? @@ -4770,22 +4743,15 @@ Static usbd_status ehci_device_isoc_transfer(struct usbd_xfer *xfer) { ehci_softc_t *sc = EHCI_XFER2SC(xfer); - usbd_status err; + usbd_status __diagused err; mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); - if (err && err != USBD_IN_PROGRESS) - return err; - return ehci_device_isoc_start(xfer); -} + KASSERT(err == USBD_NORMAL_COMPLETION); -Static usbd_status -ehci_device_isoc_start(struct usbd_xfer *xfer) -{ struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); - ehci_softc_t *sc = EHCI_XFER2SC(xfer); struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); ehci_soft_itd_t *itd, *prev; usb_dma_t *dma_buf; @@ -4801,17 +4767,6 @@ ehci_device_isoc_start(struct usbd_xfer trans_count = 0; total_length = 0; - /* - * To allow continuous transfers, above we start all transfers - * immediately. However, we're still going to get usbd_start_next call - * this when another xfer completes. So, check if this is already - * in progress or not - */ - - if (exfer->ex_isrunning) { - return USBD_IN_PROGRESS; - } - USBHIST_LOG(ehcidebug, "xfer %p flags %d", xfer, xfer->ux_flags, 0, 0); if (sc->sc_dying) @@ -5027,8 +4982,6 @@ ehci_device_isoc_start(struct usbd_xfer epipe->isoc.cur_xfers++; epipe->isoc.next_frame = frindex; - exfer->ex_isrunning = true; - ehci_add_intr_list(sc, exfer); xfer->ux_status = USBD_IN_PROGRESS; @@ -5069,10 +5022,7 @@ ehci_device_isoc_done(struct usbd_xfer * KASSERT(mutex_owned(&sc->sc_lock)); epipe->isoc.cur_xfers--; - if (exfer->ex_isrunning) { - ehci_remove_itd_chain(sc, exfer->ex_sitdstart); - exfer->ex_isrunning = false; - } + ehci_remove_itd_chain(sc, exfer->ex_sitdstart); usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); } Index: src/sys/dev/usb/ehcivar.h diff -u src/sys/dev/usb/ehcivar.h:1.42.14.22 src/sys/dev/usb/ehcivar.h:1.42.14.23 --- src/sys/dev/usb/ehcivar.h:1.42.14.22 Sun Jan 10 16:49:29 2016 +++ src/sys/dev/usb/ehcivar.h Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.42.14.22 2016/01/10 16:49:29 skrll Exp $ */ +/* $NetBSD: ehcivar.h,v 1.42.14.23 2016/03/17 09:04:53 skrll Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -103,14 +103,10 @@ struct ehci_xfer { EX_ISOC, EX_FS_ISOC } ex_type; - union { - /* ctrl/bulk/intr */ - struct { - ehci_soft_qtd_t **ex_sqtds; - size_t ex_nsqtd; - }; - /* isoc */ - bool ex_isrunning; + /* ctrl/bulk/intr */ + struct { + ehci_soft_qtd_t **ex_sqtds; + size_t ex_nsqtd; }; union { /* ctrl */ Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.254.2.58 src/sys/dev/usb/ohci.c:1.254.2.59 --- src/sys/dev/usb/ohci.c:1.254.2.58 Sun Mar 13 07:11:01 2016 +++ src/sys/dev/usb/ohci.c Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.254.2.58 2016/03/13 07:11:01 skrll Exp $ */ +/* $NetBSD: ohci.c,v 1.254.2.59 2016/03/17 09:04:53 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.58 2016/03/13 07:11:01 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.254.2.59 2016/03/17 09:04:53 skrll Exp $"); #include "opt_usb.h" @@ -74,7 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.2 #ifndef OHCI_DEBUG #define ohcidebug 0 #else -static int ohcidebug = 0; +static int ohcidebug = 10; SYSCTL_SETUP(sysctl_hw_ohci_setup, "sysctl hw.ohci setup") { @@ -205,7 +205,6 @@ Static void ohci_device_intr_done(struc Static int ohci_device_isoc_init(struct usbd_xfer *); Static void ohci_device_isoc_fini(struct usbd_xfer *); Static usbd_status ohci_device_isoc_transfer(struct usbd_xfer *); -Static usbd_status ohci_device_isoc_start(struct usbd_xfer *); Static void ohci_device_isoc_abort(struct usbd_xfer *); Static void ohci_device_isoc_close(struct usbd_pipe *); Static void ohci_device_isoc_done(struct usbd_xfer *); @@ -337,7 +336,6 @@ Static const struct usbd_pipe_methods oh .upm_init = ohci_device_isoc_init, .upm_fini = ohci_device_isoc_fini, .upm_transfer = ohci_device_isoc_transfer, - .upm_start = ohci_device_isoc_start, .upm_abort = ohci_device_isoc_abort, .upm_close = ohci_device_isoc_close, .upm_cleartoggle = ohci_noop, @@ -2218,6 +2216,7 @@ ohci_open(struct usbd_pipe *pipe) goto bad; break; case UE_ISOCHRONOUS: + pipe->up_serialise = false; pipe->up_methods = &ohci_device_isoc_methods; return ohci_setup_isoc(pipe); case UE_BULK: @@ -3541,7 +3540,7 @@ usbd_status ohci_device_isoc_transfer(struct usbd_xfer *xfer) { ohci_softc_t *sc = OHCI_XFER2SC(xfer); - usbd_status err; + usbd_status __diagused err; OHCIHIST_FUNC(); OHCIHIST_CALLED(); @@ -3552,20 +3551,13 @@ ohci_device_isoc_transfer(struct usbd_xf err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return err; - - /* XXX should check inuse here */ + KASSERT(err == USBD_NORMAL_COMPLETION); /* insert into schedule, */ ohci_device_isoc_enter(xfer); /* and start if the pipe wasn't running */ - if (!err) - ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); - - return err; + return USBD_IN_PROGRESS; } void @@ -3702,34 +3694,6 @@ ohci_device_isoc_enter(struct usbd_xfer mutex_exit(&sc->sc_lock); } -usbd_status -ohci_device_isoc_start(struct usbd_xfer *xfer) -{ - ohci_softc_t *sc = OHCI_XFER2SC(xfer); - - OHCIHIST_FUNC(); OHCIHIST_CALLED(); - DPRINTFN(5, "xfer=%p", xfer, 0, 0, 0); - - mutex_enter(&sc->sc_lock); - - if (sc->sc_dying) { - mutex_exit(&sc->sc_lock); - return USBD_IOERROR; - } - - -#ifdef DIAGNOSTIC - if (xfer->ux_status != USBD_IN_PROGRESS) - printf("ohci_device_isoc_start: not in progress %p\n", xfer); -#endif - - /* XXX anything to do? */ - - mutex_exit(&sc->sc_lock); - - return USBD_IN_PROGRESS; -} - void ohci_device_isoc_abort(struct usbd_xfer *xfer) { Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.264.4.67 src/sys/dev/usb/uhci.c:1.264.4.68 --- src/sys/dev/usb/uhci.c:1.264.4.67 Thu Mar 17 07:59:45 2016 +++ src/sys/dev/usb/uhci.c Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.264.4.67 2016/03/17 07:59:45 skrll Exp $ */ +/* $NetBSD: uhci.c,v 1.264.4.68 2016/03/17 09:04:53 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.67 2016/03/17 07:59:45 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.264.4.68 2016/03/17 09:04:53 skrll Exp $"); #include "opt_usb.h" @@ -205,7 +205,6 @@ Static void uhci_add_loop(uhci_softc_t Static void uhci_rem_loop(uhci_softc_t *); Static usbd_status uhci_setup_isoc(struct usbd_pipe *); -Static void uhci_device_isoc_enter(struct usbd_xfer *); Static struct usbd_xfer * uhci_allocx(struct usbd_bus *, unsigned int); @@ -379,7 +378,6 @@ const struct usbd_pipe_methods uhci_devi .upm_init = uhci_device_isoc_init, .upm_fini = uhci_device_isoc_fini, .upm_transfer = uhci_device_isoc_transfer, - .upm_start = uhci_device_isoc_start, .upm_abort = uhci_device_isoc_abort, .upm_close = uhci_device_isoc_close, .upm_cleartoggle = uhci_noop, @@ -3006,7 +3004,7 @@ usbd_status uhci_device_isoc_transfer(struct usbd_xfer *xfer) { uhci_softc_t *sc = UHCI_XFER2SC(xfer); - usbd_status err; + usbd_status err __diagused; UHCIHIST_FUNC(); UHCIHIST_CALLED(); DPRINTFN(5, "xfer=%p", xfer, 0, 0, 0); @@ -3016,40 +3014,23 @@ uhci_device_isoc_transfer(struct usbd_xf err = usb_insert_transfer(xfer); mutex_exit(&sc->sc_lock); - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return err; - - /* XXX should check inuse here */ + KASSERT(err == USBD_NORMAL_COMPLETION); /* insert into schedule, */ - uhci_device_isoc_enter(xfer); - /* and start if the pipe wasn't running */ - if (!err) - uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); - - return err; -} - -void -uhci_device_isoc_enter(struct usbd_xfer *xfer) -{ - uhci_softc_t *sc = UHCI_XFER2SC(xfer); struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); struct isoc *isoc = &upipe->isoc; - uhci_soft_td_t *std; + uhci_soft_td_t *std = NULL; uint32_t buf, len, status, offs; int i, next, nframes; int rd = UE_GET_DIR(upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN; - UHCIHIST_FUNC(); UHCIHIST_CALLED(); DPRINTFN(5, "used=%d next=%d xfer=%p nframes=%d", isoc->inuse, isoc->next, xfer, xfer->ux_nframes); if (sc->sc_dying) - return; + return USBD_IOERROR; if (xfer->ux_status == USBD_IN_PROGRESS) { /* This request has already been entered into the frame list */ @@ -3062,6 +3043,8 @@ uhci_device_isoc_enter(struct usbd_xfer printf("%s: overflow!\n", __func__); #endif + KASSERT(xfer->ux_nframes != 0); + mutex_enter(&sc->sc_lock); next = isoc->next; if (next == -1) { @@ -3108,44 +3091,9 @@ uhci_device_isoc_enter(struct usbd_xfer isoc->next = next; isoc->inuse += xfer->ux_nframes; - mutex_exit(&sc->sc_lock); -} - -usbd_status -uhci_device_isoc_start(struct usbd_xfer *xfer) -{ - struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); - uhci_softc_t *sc = UHCI_XFER2SC(xfer); - struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); - uhci_soft_td_t *end; - int i; - - UHCIHIST_FUNC(); UHCIHIST_CALLED(); - DPRINTFN(5, "xfer=%p", xfer, 0, 0, 0); - - mutex_enter(&sc->sc_lock); - - if (sc->sc_dying) { - mutex_exit(&sc->sc_lock); - return USBD_IOERROR; - } - -#ifdef DIAGNOSTIC - if (xfer->ux_status != USBD_IN_PROGRESS) - printf("%s: not in progress %p\n", __func__, xfer); -#endif - - /* Find the last TD */ - i = UHCI_XFER2UXFER(xfer)->ux_curframe + xfer->ux_nframes; - if (i >= UHCI_VFRAMELIST_COUNT) - i -= UHCI_VFRAMELIST_COUNT; - end = upipe->isoc.stds[i]; - - KASSERT(end != NULL); - /* Set up interrupt info. */ - ux->ux_stdstart = end; - ux->ux_stdend = end; + ux->ux_stdstart = std; + ux->ux_stdend = std; KASSERT(ux->ux_isdone); #ifdef DIAGNOSTIC @@ -3681,6 +3629,7 @@ uhci_open(struct usbd_pipe *pipe) ival = ed->bInterval; return uhci_device_setintr(sc, upipe, ival); case UE_ISOCHRONOUS: + pipe->up_serialise = false; pipe->up_methods = &uhci_device_isoc_methods; return uhci_setup_isoc(pipe); case UE_BULK: Index: src/sys/dev/usb/uhcivar.h diff -u src/sys/dev/usb/uhcivar.h:1.52.14.16 src/sys/dev/usb/uhcivar.h:1.52.14.17 --- src/sys/dev/usb/uhcivar.h:1.52.14.16 Tue Nov 10 08:44:09 2015 +++ src/sys/dev/usb/uhcivar.h Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uhcivar.h,v 1.52.14.16 2015/11/10 08:44:09 skrll Exp $ */ +/* $NetBSD: uhcivar.h,v 1.52.14.17 2016/03/17 09:04:53 skrll Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -65,14 +65,10 @@ struct uhci_xfer { enum { UX_NONE, UX_CTRL, UX_BULK, UX_INTR, UX_ISOC } ux_type; - union { - /* ctrl/bulk/intr */ - struct { - uhci_soft_td_t **ux_stds; - size_t ux_nstd; - }; - /* isoc */ - bool ux_isrunning; + /* ctrl/bulk/intr */ + struct { + uhci_soft_td_t **ux_stds; + size_t ux_nstd; }; union { /* ctrl */ Index: src/sys/dev/usb/usbdi.c diff -u src/sys/dev/usb/usbdi.c:1.162.2.43 src/sys/dev/usb/usbdi.c:1.162.2.44 --- src/sys/dev/usb/usbdi.c:1.162.2.43 Sun Feb 28 09:16:20 2016 +++ src/sys/dev/usb/usbdi.c Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.162.2.43 2016/02/28 09:16:20 skrll Exp $ */ +/* $NetBSD: usbdi.c,v 1.162.2.44 2016/03/17 09:04:53 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.43 2016/02/28 09:16:20 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.162.2.44 2016/03/17 09:04:53 skrll Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -331,7 +331,8 @@ usbd_transfer(struct usbd_xfer *xfer) */ usbd_lock_pipe(pipe); SIMPLEQ_REMOVE_HEAD(&pipe->up_queue, ux_next); - usbd_start_next(pipe); + if (pipe->up_serialise) + usbd_start_next(pipe); usbd_unlock_pipe(pipe); } @@ -988,7 +989,7 @@ usb_transfer_complete(struct usbd_xfer * if (erred && pipe->up_iface != NULL) /* not control pipe */ pipe->up_running = 0; } - if (pipe->up_running) + if (pipe->up_running && pipe->up_serialise) usbd_start_next(pipe); } @@ -1011,7 +1012,7 @@ usb_insert_transfer(struct usbd_xfer *xf xfer->ux_state = XFER_ONQU; #endif SIMPLEQ_INSERT_TAIL(&pipe->up_queue, xfer, ux_next); - if (pipe->up_running) + if (pipe->up_running && pipe->up_serialise) err = USBD_IN_PROGRESS; else { pipe->up_running = 1; @@ -1033,6 +1034,7 @@ usbd_start_next(struct usbd_pipe *pipe) KASSERT(pipe != NULL); KASSERT(pipe->up_methods != NULL); KASSERT(pipe->up_methods->upm_start != NULL); + KASSERT(pipe->up_serialise == true); int polling = pipe->up_dev->ud_bus->ub_usepolling; KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock)); Index: src/sys/dev/usb/usbdivar.h diff -u src/sys/dev/usb/usbdivar.h:1.109.2.24 src/sys/dev/usb/usbdivar.h:1.109.2.25 --- src/sys/dev/usb/usbdivar.h:1.109.2.24 Sun Mar 6 10:25:31 2016 +++ src/sys/dev/usb/usbdivar.h Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdivar.h,v 1.109.2.24 2016/03/06 10:25:31 skrll Exp $ */ +/* $NetBSD: usbdivar.h,v 1.109.2.25 2016/03/17 09:04:53 skrll Exp $ */ /* * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc. @@ -222,6 +222,7 @@ struct usbd_pipe { struct usbd_endpoint *up_endpoint; char up_running; char up_aborting; + bool up_serialise; SIMPLEQ_HEAD(, usbd_xfer) up_queue; LIST_ENTRY(usbd_pipe) up_next; struct usb_task up_async_task; Index: src/sys/external/bsd/dwc2/dwc2.c diff -u src/sys/external/bsd/dwc2/dwc2.c:1.32.2.23 src/sys/external/bsd/dwc2/dwc2.c:1.32.2.24 --- src/sys/external/bsd/dwc2/dwc2.c:1.32.2.23 Sat Mar 5 13:03:00 2016 +++ src/sys/external/bsd/dwc2/dwc2.c Thu Mar 17 09:04:53 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: dwc2.c,v 1.32.2.23 2016/03/05 13:03:00 skrll Exp $ */ +/* $NetBSD: dwc2.c,v 1.32.2.24 2016/03/17 09:04:53 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.23 2016/03/05 13:03:00 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.32.2.24 2016/03/17 09:04:53 skrll Exp $"); #include "opt_usb.h" @@ -104,7 +104,6 @@ Static void dwc2_device_ctrl_close(stru Static void dwc2_device_ctrl_done(struct usbd_xfer *); Static usbd_status dwc2_device_bulk_transfer(struct usbd_xfer *); -Static usbd_status dwc2_device_bulk_start(struct usbd_xfer *); Static void dwc2_device_bulk_abort(struct usbd_xfer *); Static void dwc2_device_bulk_close(struct usbd_pipe *); Static void dwc2_device_bulk_done(struct usbd_xfer *); @@ -116,7 +115,6 @@ Static void dwc2_device_intr_close(stru Static void dwc2_device_intr_done(struct usbd_xfer *); Static usbd_status dwc2_device_isoc_transfer(struct usbd_xfer *); -Static usbd_status dwc2_device_isoc_start(struct usbd_xfer *); Static void dwc2_device_isoc_abort(struct usbd_xfer *); Static void dwc2_device_isoc_close(struct usbd_pipe *); Static void dwc2_device_isoc_done(struct usbd_xfer *); @@ -187,7 +185,6 @@ Static const struct usbd_pipe_methods dw Static const struct usbd_pipe_methods dwc2_device_bulk_methods = { .upm_transfer = dwc2_device_bulk_transfer, - .upm_start = dwc2_device_bulk_start, .upm_abort = dwc2_device_bulk_abort, .upm_close = dwc2_device_bulk_close, .upm_cleartoggle = dwc2_device_clear_toggle, @@ -196,7 +193,6 @@ Static const struct usbd_pipe_methods dw Static const struct usbd_pipe_methods dwc2_device_isoc_methods = { .upm_transfer = dwc2_device_isoc_transfer, - .upm_start = dwc2_device_isoc_start, .upm_abort = dwc2_device_isoc_abort, .upm_close = dwc2_device_isoc_close, .upm_cleartoggle = dwc2_noop, @@ -435,9 +431,11 @@ dwc2_open(struct usbd_pipe *pipe) pipe->up_methods = &dwc2_device_intr_methods; break; case UE_ISOCHRONOUS: + pipe->up_serialise = false; pipe->up_methods = &dwc2_device_isoc_methods; break; case UE_BULK: + pipe->up_serialise = false; pipe->up_methods = &dwc2_device_bulk_methods; break; default: @@ -790,22 +788,9 @@ dwc2_device_bulk_transfer(struct usbd_xf /* Insert last in queue. */ mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); - if (err) - return err; - /* Pipe isn't running, start first */ - return dwc2_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); -} + KASSERT(err == USBD_NORMAL_COMPLETION); -Static usbd_status -dwc2_device_bulk_start(struct usbd_xfer *xfer) -{ - struct dwc2_softc *sc = DWC2_XFER2SC(xfer); - usbd_status err; - - DPRINTF("xfer=%p\n", xfer); - mutex_enter(&sc->sc_lock); xfer->ux_status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); mutex_exit(&sc->sc_lock); @@ -929,23 +914,9 @@ dwc2_device_isoc_transfer(struct usbd_xf /* Insert last in queue. */ mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); - if (err) - return err; - - /* Pipe isn't running, start first */ - return dwc2_device_isoc_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); -} -usbd_status -dwc2_device_isoc_start(struct usbd_xfer *xfer) -{ - struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer); - struct usbd_device *dev = dpipe->pipe.up_dev; - struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv; - usbd_status err; + KASSERT(err == USBD_NORMAL_COMPLETION); - mutex_enter(&sc->sc_lock); xfer->ux_status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); mutex_exit(&sc->sc_lock);