Module Name: src Committed By: mrg Date: Fri Dec 9 01:53:00 UTC 2011
Modified Files: src/sys/dev/pci [jmcneill-usbmp]: ehci_pci.c ohci_pci.c uhci_pci.c src/sys/dev/usb [jmcneill-usbmp]: ehci.c ohci.c uaudio.c uhci.c umidi.c usb.c usb_subr.c usbdi.c usbdivar.h Log Message: - make pipe->close method take the thread lock - convert usb_taskq to use mutex/cv - convert needs_explore usage into a cv on the thread lock - remove KERNEL_*LOCK from uaudio and umidi, since we're supposedly MPSAFE here now - use IPL_SCHED instead of IPL_USB (aka biglocked) interrupts - drop the audio thread lock when calling into usb when it may sleep, avoiding a deadlock between audiowrite and audioioctl. this fixes mixerctl -a vs. playing hanging the system XXX probably need to check this in a bunch more places. To generate a diff of this commit: cvs rdiff -u -r1.53.6.1 -r1.53.6.2 src/sys/dev/pci/ehci_pci.c cvs rdiff -u -r1.47 -r1.47.8.1 src/sys/dev/pci/ohci_pci.c cvs rdiff -u -r1.53 -r1.53.8.1 src/sys/dev/pci/uhci_pci.c cvs rdiff -u -r1.181.6.4 -r1.181.6.5 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.218.6.7 -r1.218.6.8 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.124 -r1.124.2.1 src/sys/dev/usb/uaudio.c cvs rdiff -u -r1.240.6.5 -r1.240.6.6 src/sys/dev/usb/uhci.c cvs rdiff -u -r1.53 -r1.53.2.1 src/sys/dev/usb/umidi.c cvs rdiff -u -r1.125.6.4 -r1.125.6.5 src/sys/dev/usb/usb.c cvs rdiff -u -r1.180.6.2 -r1.180.6.3 src/sys/dev/usb/usb_subr.c cvs rdiff -u -r1.134.2.4 -r1.134.2.5 src/sys/dev/usb/usbdi.c cvs rdiff -u -r1.93.8.3 -r1.93.8.4 src/sys/dev/usb/usbdivar.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/pci/ehci_pci.c diff -u src/sys/dev/pci/ehci_pci.c:1.53.6.1 src/sys/dev/pci/ehci_pci.c:1.53.6.2 --- src/sys/dev/pci/ehci_pci.c:1.53.6.1 Sun Dec 4 13:23:16 2011 +++ src/sys/dev/pci/ehci_pci.c Fri Dec 9 01:52:59 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci_pci.c,v 1.53.6.1 2011/12/04 13:23:16 jmcneill Exp $ */ +/* $NetBSD: ehci_pci.c,v 1.53.6.2 2011/12/09 01:52:59 mrg Exp $ */ /* * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.53.6.1 2011/12/04 13:23:16 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.53.6.2 2011/12/09 01:52:59 mrg Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -182,7 +182,7 @@ ehci_pci_attach(device_t parent, device_ * Allocate IRQ */ intrstr = pci_intr_string(pc, ih); - sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ehci_intr, sc); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_SCHED, ehci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) Index: src/sys/dev/pci/ohci_pci.c diff -u src/sys/dev/pci/ohci_pci.c:1.47 src/sys/dev/pci/ohci_pci.c:1.47.8.1 --- src/sys/dev/pci/ohci_pci.c:1.47 Mon Apr 4 22:48:15 2011 +++ src/sys/dev/pci/ohci_pci.c Fri Dec 9 01:52:59 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci_pci.c,v 1.47 2011/04/04 22:48:15 dyoung Exp $ */ +/* $NetBSD: ohci_pci.c,v 1.47.8.1 2011/12/09 01:52:59 mrg Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci_pci.c,v 1.47 2011/04/04 22:48:15 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci_pci.c,v 1.47.8.1 2011/12/09 01:52:59 mrg Exp $"); #include "ehci.h" @@ -131,7 +131,7 @@ ohci_pci_attach(device_t parent, device_ * Allocate IRQ */ intrstr = pci_intr_string(pc, ih); - sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ohci_intr, sc); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_SCHED, ohci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) Index: src/sys/dev/pci/uhci_pci.c diff -u src/sys/dev/pci/uhci_pci.c:1.53 src/sys/dev/pci/uhci_pci.c:1.53.8.1 --- src/sys/dev/pci/uhci_pci.c:1.53 Mon Apr 4 22:48:15 2011 +++ src/sys/dev/pci/uhci_pci.c Fri Dec 9 01:52:59 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci_pci.c,v 1.53 2011/04/04 22:48:15 dyoung Exp $ */ +/* $NetBSD: uhci_pci.c,v 1.53.8.1 2011/12/09 01:52:59 mrg Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.53 2011/04/04 22:48:15 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.53.8.1 2011/12/09 01:52:59 mrg Exp $"); #include "ehci.h" @@ -134,7 +134,7 @@ uhci_pci_attach(device_t parent, device_ return; } intrstr = pci_intr_string(pc, ih); - sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, uhci_intr, sc); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_SCHED, uhci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.181.6.4 src/sys/dev/usb/ehci.c:1.181.6.5 --- src/sys/dev/usb/ehci.c:1.181.6.4 Thu Dec 8 02:51:07 2011 +++ src/sys/dev/usb/ehci.c Fri Dec 9 01:52:59 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.181.6.4 2011/12/08 02:51:07 mrg Exp $ */ +/* $NetBSD: ehci.c,v 1.181.6.5 2011/12/09 01:52:59 mrg Exp $ */ /* * Copyright (c) 2004-2011 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.181.6.4 2011/12/08 02:51:07 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.181.6.5 2011/12/09 01:52:59 mrg Exp $"); #include "ohci.h" #include "uhci.h" @@ -352,7 +352,7 @@ ehci_init(ehci_softc_t *sc) #endif mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); - mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); cv_init(&sc->sc_softwake_cv, "ehciab"); cv_init(&sc->sc_doorbell, "ehcidi"); @@ -2616,11 +2616,11 @@ ehci_root_intr_close(usbd_pipe_handle pi { ehci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ehci_root_intr_close\n")); - mutex_enter(&sc->sc_lock); sc->sc_intrxfer = NULL; - mutex_exit(&sc->sc_lock); } Static void @@ -3346,11 +3346,11 @@ ehci_device_ctrl_close(usbd_pipe_handle ehci_softc_t *sc = pipe->device->bus->hci_private; /*struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;*/ + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ehci_device_ctrl_close: pipe=%p\n", pipe)); - mutex_enter(&sc->sc_lock); ehci_close_pipe(pipe, sc->sc_async_head); - mutex_exit(&sc->sc_lock); } Static usbd_status @@ -3663,11 +3663,11 @@ ehci_device_bulk_close(usbd_pipe_handle ehci_softc_t *sc = pipe->device->bus->hci_private; struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ehci_device_bulk_close: pipe=%p\n", pipe)); - mutex_enter(&sc->sc_lock); pipe->endpoint->datatoggle = epipe->nexttoggle; ehci_close_pipe(pipe, sc->sc_async_head); - mutex_exit(&sc->sc_lock); } Static void @@ -3848,6 +3848,8 @@ ehci_device_intr_close(usbd_pipe_handle struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; struct ehci_soft_islot *isp; + KASSERT(mutex_owned(&sc->sc_lock)); + isp = &sc->sc_islots[epipe->sqh->islot]; ehci_close_pipe(pipe, isp->sqh); } Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.218.6.7 src/sys/dev/usb/ohci.c:1.218.6.8 --- src/sys/dev/usb/ohci.c:1.218.6.7 Thu Dec 8 22:38:47 2011 +++ src/sys/dev/usb/ohci.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.218.6.7 2011/12/08 22:38:47 mrg Exp $ */ +/* $NetBSD: ohci.c,v 1.218.6.8 2011/12/09 01:53:00 mrg Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.7 2011/12/08 22:38:47 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.8 2011/12/09 01:53:00 mrg Exp $"); #include "opt_usb.h" @@ -665,7 +665,7 @@ ohci_init(ohci_softc_t *sc) callout_init(&sc->sc_tmo_rhsc, CALLOUT_MPSAFE); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); - mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); cv_init(&sc->sc_softwake_cv, "ohciab"); sc->sc_rhsc_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, @@ -2895,6 +2895,8 @@ ohci_root_intr_close(usbd_pipe_handle pi { ohci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ohci_root_intr_close\n")); sc->sc_intrxfer = NULL; @@ -2962,11 +2964,11 @@ ohci_device_ctrl_close(usbd_pipe_handle struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; ohci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); - mutex_enter(&sc->sc_lock); ohci_close_pipe(pipe, sc->sc_ctrl_head); ohci_free_std(sc, opipe->tail.td); - mutex_exit(&sc->sc_lock); } /************************/ @@ -3126,11 +3128,11 @@ ohci_device_bulk_close(usbd_pipe_handle struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; ohci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); - mutex_enter(&sc->sc_lock); ohci_close_pipe(pipe, sc->sc_bulk_head); ohci_free_std(sc, opipe->tail.td); - mutex_exit(&sc->sc_lock); } /************************/ @@ -3262,9 +3264,10 @@ ohci_device_intr_close(usbd_pipe_handle int j; ohci_soft_ed_t *p, *sed = opipe->sed; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", pipe, nslots, pos)); - mutex_enter(&sc->sc_lock); usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); @@ -3286,7 +3289,6 @@ ohci_device_intr_close(usbd_pipe_handle usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), sizeof(p->ed.ed_nexted), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - mutex_exit(&sc->sc_lock); for (j = 0; j < nslots; j++) --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; @@ -3648,12 +3650,12 @@ ohci_device_isoc_close(usbd_pipe_handle struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; ohci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); - mutex_enter(&sc->sc_lock); ohci_close_pipe(pipe, sc->sc_isoc_head); #ifdef DIAGNOSTIC opipe->tail.itd->isdone = 1; #endif ohci_free_sitd(sc, opipe->tail.itd); - mutex_exit(&sc->sc_lock); } Index: src/sys/dev/usb/uaudio.c diff -u src/sys/dev/usb/uaudio.c:1.124 src/sys/dev/usb/uaudio.c:1.124.2.1 --- src/sys/dev/usb/uaudio.c:1.124 Sun Nov 27 07:36:54 2011 +++ src/sys/dev/usb/uaudio.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uaudio.c,v 1.124 2011/11/27 07:36:54 mrg Exp $ */ +/* $NetBSD: uaudio.c,v 1.124.2.1 2011/12/09 01:53:00 mrg Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.124 2011/11/27 07:36:54 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.124.2.1 2011/12/09 01:53:00 mrg Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -421,7 +421,7 @@ uaudio_attach(device_t parent, device_t sc->sc_dev = self; sc->sc_udev = uaa->device; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); - mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); strlcpy(sc->sc_adev.name, "USB audio", sizeof(sc->sc_adev.name)); strlcpy(sc->sc_adev.version, "", sizeof(sc->sc_adev.version)); @@ -2097,7 +2097,7 @@ uaudio_query_devinfo(void *addr, mixer_d struct mixerctl *mc; int n, nctls, i; - DPRINTFN(2, "index=%d\n", mi->index); + DPRINTFN(7, "index=%d\n", mi->index); sc = addr; if (sc->sc_dying) return EIO; @@ -2220,7 +2220,6 @@ uaudio_halt_out_dma(void *addr) DPRINTF("%s", "enter\n"); - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); if (sc->sc_playchan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_playchan); @@ -2229,7 +2228,6 @@ uaudio_halt_out_dma(void *addr) sc->sc_playchan.intr = NULL; } mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return 0; } @@ -2241,7 +2239,6 @@ uaudio_halt_in_dma(void *addr) DPRINTF("%s", "enter\n"); - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); if (sc->sc_recchan.pipe != NULL) { uaudio_chan_close(sc, &sc->sc_recchan); @@ -2250,7 +2247,6 @@ uaudio_halt_in_dma(void *addr) sc->sc_recchan.intr = NULL; } mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return 0; } @@ -2464,10 +2460,10 @@ uaudio_ctl_get(struct uaudio_softc *sc, int val; DPRINTFN(5,"which=%d chan=%d\n", which, chan); - KERNEL_LOCK(1, curlwp); + mutex_exit(&sc->sc_lock); val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan], mc->wIndex, MIX_SIZE(mc->type)); - KERNEL_UNLOCK_ONE(curlwp); + mutex_enter(&sc->sc_lock); return uaudio_value2bsd(mc, val); } @@ -2477,10 +2473,10 @@ uaudio_ctl_set(struct uaudio_softc *sc, { val = uaudio_bsd2value(mc, val); - KERNEL_LOCK(1, curlwp); + mutex_exit(&sc->sc_lock); uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan], mc->wIndex, MIX_SIZE(mc->type), val); - KERNEL_UNLOCK_ONE(curlwp); + mutex_enter(&sc->sc_lock); } Static int @@ -2592,18 +2588,15 @@ uaudio_trigger_input(void *addr, void *s "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, ch->fraction); - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); err = uaudio_chan_alloc_buffers(sc, ch); if (err) { mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return EIO; } err = uaudio_chan_open(sc, ch); mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); if (err) { uaudio_chan_free_buffers(sc, ch); return EIO; @@ -2612,14 +2605,12 @@ uaudio_trigger_input(void *addr, void *s ch->intr = intr; ch->arg = arg; - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); s = splusb(); for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */ uaudio_chan_rtransfer(ch); splx(s); mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return 0; } @@ -2646,18 +2637,15 @@ uaudio_trigger_output(void *addr, void * "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, ch->fraction); - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); err = uaudio_chan_alloc_buffers(sc, ch); if (err) { mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return EIO; } err = uaudio_chan_open(sc, ch); mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); if (err) { uaudio_chan_free_buffers(sc, ch); return EIO; @@ -2666,14 +2654,12 @@ uaudio_trigger_output(void *addr, void * ch->intr = intr; ch->arg = arg; - KERNEL_LOCK(1, curlwp); mutex_spin_exit(&sc->sc_intr_lock); s = splusb(); for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */ uaudio_chan_ptransfer(ch); splx(s); mutex_spin_enter(&sc->sc_intr_lock); - KERNEL_UNLOCK_ONE(curlwp); return 0; } @@ -3129,9 +3115,7 @@ uaudio_set_speed(struct uaudio_softc *sc data[1] = speed >> 8; data[2] = speed >> 16; - KERNEL_LOCK(1, curlwp); err = usbd_do_request(sc->sc_udev, &req, data); - KERNEL_UNLOCK_ONE(curlwp); return err; } Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.240.6.5 src/sys/dev/usb/uhci.c:1.240.6.6 --- src/sys/dev/usb/uhci.c:1.240.6.5 Thu Dec 8 02:51:08 2011 +++ src/sys/dev/usb/uhci.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.240.6.5 2011/12/08 02:51:08 mrg Exp $ */ +/* $NetBSD: uhci.c,v 1.240.6.6 2011/12/09 01:53:00 mrg Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.240.6.5 2011/12/08 02:51:08 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.240.6.6 2011/12/09 01:53:00 mrg Exp $"); #include "opt_usb.h" @@ -529,7 +529,7 @@ uhci_init(uhci_softc_t *sc) callout_init(&sc->sc_poll_handle, CALLOUT_MPSAFE); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); - mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); cv_init(&sc->sc_softwake_cv, "uhciab"); /* Set up the bus struct. */ @@ -2217,6 +2217,8 @@ uhci_device_bulk_close(usbd_pipe_handle usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = dev->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + uhci_free_sqh(sc, upipe->u.bulk.sqh); pipe->endpoint->datatoggle = upipe->nexttoggle; @@ -2407,12 +2409,12 @@ uhci_device_intr_close(usbd_pipe_handle uhci_softc_t *sc = pipe->device->bus->hci_private; int i, npoll; + KASSERT(mutex_owned(&sc->sc_lock)); + /* Unlink descriptors from controller data structures. */ npoll = upipe->u.intr.npoll; - mutex_enter(&sc->sc_lock); for (i = 0; i < npoll; i++) uhci_remove_intr(sc, upipe->u.intr.qhs[i]); - mutex_exit(&sc->sc_lock); /* * We now have to wait for any activity on the physical @@ -2792,6 +2794,8 @@ uhci_device_isoc_close(usbd_pipe_handle struct iso *iso; int i; + KASSERT(mutex_owned(&sc->sc_lock)); + /* * Make sure all TDs are marked as inactive. * Wait for completion. @@ -2800,7 +2804,6 @@ uhci_device_isoc_close(usbd_pipe_handle */ iso = &upipe->u.iso; - mutex_enter(&sc->sc_lock); for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = iso->stds[i]; usb_syncmem(&std->dma, @@ -2839,7 +2842,6 @@ uhci_device_isoc_close(usbd_pipe_handle BUS_DMASYNC_PREWRITE); uhci_free_std(sc, std); } - mutex_exit(&sc->sc_lock); kmem_free(iso->stds, UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *)); } @@ -3918,6 +3920,8 @@ uhci_root_intr_close(usbd_pipe_handle pi { uhci_softc_t *sc = pipe->device->bus->hci_private; + KASSERT(mutex_owned(&sc->sc_lock)); + callout_stop(&sc->sc_poll_handle); sc->sc_intr_xfer = NULL; DPRINTF(("uhci_root_intr_close\n")); Index: src/sys/dev/usb/umidi.c diff -u src/sys/dev/usb/umidi.c:1.53 src/sys/dev/usb/umidi.c:1.53.2.1 --- src/sys/dev/usb/umidi.c:1.53 Sat Nov 26 13:31:52 2011 +++ src/sys/dev/usb/umidi.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: umidi.c,v 1.53 2011/11/26 13:31:52 mrg Exp $ */ +/* $NetBSD: umidi.c,v 1.53.2.1 2011/12/09 01:53:00 mrg Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.53 2011/11/26 13:31:52 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.53.2.1 2011/12/09 01:53:00 mrg Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -209,7 +209,6 @@ umidi_attach(device_t parent, device_t s mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_USB); cv_init(&sc->sc_cv, "umidopcl"); - KERNEL_LOCK(1, curlwp); err = alloc_all_endpoints(sc); if (err != USBD_NORMAL_COMPLETION) { aprint_error_dev(self, @@ -242,7 +241,6 @@ umidi_attach(device_t parent, device_t s aprint_error_dev(self, "attach_all_mididevs failed. (err=%d)\n", err); } - KERNEL_UNLOCK_ONE(curlwp); #ifdef UMIDI_DEBUG dump_sc(sc); @@ -299,7 +297,6 @@ umidi_detach(device_t self, int flags) DPRINTFN(1,("umidi_detach\n")); sc->sc_dying = 1; - KERNEL_LOCK(1, curlwp); detach_all_mididevs(sc, flags); free_all_mididevs(sc); free_all_jacks(sc); @@ -307,7 +304,6 @@ umidi_detach(device_t self, int flags) usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - KERNEL_UNLOCK_ONE(curlwp); mutex_destroy(&sc->sc_lock); cv_destroy(&sc->sc_cv); @@ -1433,13 +1429,11 @@ start_output_transfer(struct umidi_endpo length = (ep->next_slot - ep->buffer) * sizeof *ep->buffer; DPRINTFN(200,("umidi out transfer: start %p end %p length %u\n", ep->buffer, ep->next_slot, length)); - KERNEL_LOCK(1, curlwp); usbd_setup_xfer(ep->xfer, ep->pipe, (usbd_private_handle)ep, ep->buffer, length, USBD_NO_COPY, USBD_NO_TIMEOUT, out_intr); rv = usbd_transfer(ep->xfer); - KERNEL_UNLOCK_ONE(curlwp); /* * Once the transfer is scheduled, no more adding to partial Index: src/sys/dev/usb/usb.c diff -u src/sys/dev/usb/usb.c:1.125.6.4 src/sys/dev/usb/usb.c:1.125.6.5 --- src/sys/dev/usb/usb.c:1.125.6.4 Thu Dec 8 02:51:08 2011 +++ src/sys/dev/usb/usb.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.125.6.4 2011/12/08 02:51:08 mrg Exp $ */ +/* $NetBSD: usb.c,v 1.125.6.5 2011/12/09 01:53:00 mrg Exp $ */ /* * Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.4 2011/12/08 02:51:08 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.5 2011/12/09 01:53:00 mrg Exp $"); #include "opt_compat_netbsd.h" #include "opt_usb.h" @@ -100,6 +100,8 @@ struct usb_softc { struct usb_taskq { TAILQ_HEAD(, usb_task) tasks; + kmutex_t lock; + kcondvar_t cv; struct lwp *task_thread_lwp; const char *name; int taskcreated; /* task thread exists. */ @@ -232,6 +234,7 @@ usb_doattach(device_t self) } else { sc->sc_bus->intr_lock = sc->sc_bus->lock = NULL; } + cv_init(&sc->sc_bus->needs_explore_cv, "usbevt"); ue = usb_alloc_event(); ue->u.ue_ctrlr.ue_bus = device_unit(self); @@ -308,6 +311,8 @@ usb_create_event_thread(device_t self) continue; TAILQ_INIT(&taskq->tasks); + mutex_init(&taskq->lock, MUTEX_DEFAULT, IPL_NONE); + cv_init(&taskq->cv, "usbtsk"); taskq->taskcreated = 1; taskq->name = taskq_names[i]; if (kthread_create(PRI_NONE, 0, NULL, usb_task_thread, @@ -327,10 +332,9 @@ void usb_add_task(usbd_device_handle dev, struct usb_task *task, int queue) { struct usb_taskq *taskq; - int s; taskq = &usb_taskq[queue]; - s = splusb(); + mutex_enter(&taskq->lock); if (task->queue == -1) { DPRINTFN(2,("usb_add_task: task=%p\n", task)); TAILQ_INSERT_TAIL(&taskq->tasks, task, next); @@ -338,23 +342,22 @@ usb_add_task(usbd_device_handle dev, str } else { DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); } - wakeup(&taskq->tasks); - splx(s); + cv_signal(&taskq->cv); + mutex_exit(&taskq->lock); } void usb_rem_task(usbd_device_handle dev, struct usb_task *task) { struct usb_taskq *taskq; - int s; taskq = &usb_taskq[task->queue]; - s = splusb(); + mutex_enter(&taskq->lock); if (task->queue != -1) { TAILQ_REMOVE(&taskq->tasks, task, next); task->queue = -1; } - splx(s); + mutex_exit(&taskq->lock); } void @@ -375,21 +378,36 @@ usb_event_thread(void *arg) usb_delay_ms(sc->sc_bus, 500); /* Make sure first discover does something. */ + if (sc->sc_bus->lock) + mutex_enter(sc->sc_bus->lock); sc->sc_bus->needs_explore = 1; usb_discover(sc); + if (sc->sc_bus->lock) + mutex_exit(sc->sc_bus->lock); config_pending_decr(); + if (sc->sc_bus->lock) + mutex_enter(sc->sc_bus->lock); while (!sc->sc_dying) { if (usb_noexplore < 2) usb_discover(sc); - (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", - usb_noexplore ? 0 : hz * 60); + + if (sc->sc_bus->lock) + cv_timedwait(&sc->sc_bus->needs_explore_cv, + sc->sc_bus->lock, usb_noexplore ? 0 : hz * 60); + else + (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, + "usbevt", usb_noexplore ? 0 : hz * 60); DPRINTFN(2,("usb_event_thread: woke up\n")); } sc->sc_event_thread = NULL; /* In case parent is waiting for us to exit. */ - wakeup(sc); + if (sc->sc_bus->lock) { + cv_signal(&sc->sc_bus->needs_explore_cv); + mutex_exit(sc->sc_bus->lock); + } else + wakeup(sc); DPRINTF(("usb_event_thread: exit\n")); kthread_exit(0); @@ -400,27 +418,27 @@ usb_task_thread(void *arg) { struct usb_task *task; struct usb_taskq *taskq; - int s; taskq = arg; DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name)); - s = splusb(); + mutex_enter(&taskq->lock); for (;;) { task = TAILQ_FIRST(&taskq->tasks); if (task == NULL) { - tsleep(&taskq->tasks, PWAIT, "usbtsk", 0); + cv_wait(&taskq->cv, &taskq->lock); task = TAILQ_FIRST(&taskq->tasks); } DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task)); if (task != NULL) { TAILQ_REMOVE(&taskq->tasks, task, next); task->queue = -1; - splx(s); + mutex_exit(&taskq->lock); task->fun(task->arg); - s = splusb(); + mutex_enter(&taskq->lock); } } + mutex_exit(&taskq->lock); } int @@ -777,6 +795,8 @@ Static void usb_discover(struct usb_softc *sc) { + KASSERT(sc->sc_bus->lock == NULL || mutex_owned(sc->sc_bus->lock)); + DPRINTFN(2,("usb_discover\n")); if (usb_noexplore > 1) return; @@ -784,10 +804,16 @@ usb_discover(struct usb_softc *sc) * We need mutual exclusion while traversing the device tree, * but this is guaranteed since this function is only called * from the event thread for the controller. + * + * Also, we now have sc_bus->lock held for MPSAFE controllers. */ while (sc->sc_bus->needs_explore && !sc->sc_dying) { sc->sc_bus->needs_explore = 0; + if (sc->sc_bus->lock) + mutex_exit(sc->sc_bus->lock); sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); + if (sc->sc_bus->lock) + mutex_enter(sc->sc_bus->lock); } } @@ -795,17 +821,29 @@ void usb_needs_explore(usbd_device_handle dev) { DPRINTFN(2,("usb_needs_explore\n")); + if (dev->bus->lock) + mutex_enter(dev->bus->lock); dev->bus->needs_explore = 1; - wakeup(&dev->bus->needs_explore); + if (dev->bus->lock) { + cv_signal(&dev->bus->needs_explore_cv); + mutex_exit(dev->bus->lock); + } else + wakeup(&dev->bus->needs_explore); } void usb_needs_reattach(usbd_device_handle dev) { DPRINTFN(2,("usb_needs_reattach\n")); + if (dev->bus->lock) + mutex_enter(dev->bus->lock); dev->powersrc->reattach = 1; dev->bus->needs_explore = 1; - wakeup(&dev->bus->needs_explore); + if (dev->bus->lock) { + cv_signal(&dev->bus->needs_explore_cv); + mutex_exit(dev->bus->lock); + } else + wakeup(&dev->bus->needs_explore); } /* Called at splusb() */ @@ -967,8 +1005,16 @@ usb_detach(device_t self, int flags) /* Kill off event thread. */ sc->sc_dying = 1; while (sc->sc_event_thread != NULL) { - wakeup(&sc->sc_bus->needs_explore); - tsleep(sc, PWAIT, "usbdet", hz * 60); + if (sc->sc_bus->lock) { + mutex_enter(sc->sc_bus->lock); + cv_signal(&sc->sc_bus->needs_explore_cv); + cv_timedwait(&sc->sc_bus->needs_explore_cv, + sc->sc_bus->lock, hz * 60); + mutex_exit(sc->sc_bus->lock); + } else { + wakeup(&sc->sc_bus->needs_explore); + tsleep(sc, PWAIT, "usbdet", hz * 60); + } } DPRINTF(("usb_detach: event thread dead\n")); Index: src/sys/dev/usb/usb_subr.c diff -u src/sys/dev/usb/usb_subr.c:1.180.6.2 src/sys/dev/usb/usb_subr.c:1.180.6.3 --- src/sys/dev/usb/usb_subr.c:1.180.6.2 Thu Dec 8 02:51:08 2011 +++ src/sys/dev/usb/usb_subr.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: usb_subr.c,v 1.180.6.2 2011/12/08 02:51:08 mrg Exp $ */ +/* $NetBSD: usb_subr.c,v 1.180.6.3 2011/12/09 01:53:00 mrg Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.180.6.2 2011/12/08 02:51:08 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.180.6.3 2011/12/09 01:53:00 mrg Exp $"); #include "opt_compat_netbsd.h" #include "opt_usbverbose.h" @@ -759,8 +759,12 @@ usbd_setup_pipe(usbd_device_handle dev, void usbd_kill_pipe(usbd_pipe_handle pipe) { + int s; + usbd_abort_pipe(pipe); + usbd_lock_pipe(pipe); pipe->methods->close(pipe); + usbd_unlock_pipe(pipe); pipe->endpoint->refcnt--; free(pipe, M_USB); } @@ -1280,6 +1284,7 @@ usbd_reload_device_desc(usbd_device_hand void usbd_remove_device(usbd_device_handle dev, struct usbd_port *up) { + DPRINTF(("usbd_remove_device: %p\n", dev)); if (dev->default_pipe != NULL) Index: src/sys/dev/usb/usbdi.c diff -u src/sys/dev/usb/usbdi.c:1.134.2.4 src/sys/dev/usb/usbdi.c:1.134.2.5 --- src/sys/dev/usb/usbdi.c:1.134.2.4 Thu Dec 8 22:38:47 2011 +++ src/sys/dev/usb/usbdi.c Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.134.2.4 2011/12/08 22:38:47 mrg Exp $ */ +/* $NetBSD: usbdi.c,v 1.134.2.5 2011/12/09 01:53:00 mrg Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ /* @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.4 2011/12/08 22:38:47 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.5 2011/12/09 01:53:00 mrg Exp $"); #include "opt_compat_netbsd.h" #include "opt_usb.h" @@ -229,6 +229,7 @@ usbd_open_pipe_intr(usbd_interface_handl usbd_status usbd_close_pipe(usbd_pipe_handle pipe) { + int s; #ifdef DIAGNOSTIC if (pipe == NULL) { @@ -237,13 +238,19 @@ usbd_close_pipe(usbd_pipe_handle pipe) } #endif - if (--pipe->refcnt != 0) + usbd_lock_pipe(pipe); + if (--pipe->refcnt != 0) { + usbd_unlock_pipe(pipe); return (USBD_NORMAL_COMPLETION); - if (! SIMPLEQ_EMPTY(&pipe->queue)) + } + if (! SIMPLEQ_EMPTY(&pipe->queue)) { + usbd_unlock_pipe(pipe); return (USBD_PENDING_REQUESTS); + } LIST_REMOVE(pipe, next); pipe->endpoint->refcnt--; pipe->methods->close(pipe); + usbd_unlock_pipe(pipe); if (pipe->intrxfer != NULL) usbd_free_xfer(pipe->intrxfer); free(pipe, M_USB); Index: src/sys/dev/usb/usbdivar.h diff -u src/sys/dev/usb/usbdivar.h:1.93.8.3 src/sys/dev/usb/usbdivar.h:1.93.8.4 --- src/sys/dev/usb/usbdivar.h:1.93.8.3 Thu Dec 8 22:38:47 2011 +++ src/sys/dev/usb/usbdivar.h Fri Dec 9 01:53:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdivar.h,v 1.93.8.3 2011/12/08 22:38:47 mrg Exp $ */ +/* $NetBSD: usbdivar.h,v 1.93.8.4 2011/12/09 01:53:00 mrg Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ /* @@ -61,7 +61,7 @@ * transfer - - * start - - * abort - - - * close - - + * close - x * cleartoggle - - * done - x * @@ -146,6 +146,7 @@ struct usbd_bus { kmutex_t *lock; struct usbd_device *root_hub; usbd_device_handle devices[USB_MAX_DEVICES]; + kcondvar_t needs_explore_cv; char needs_explore;/* a hub a signalled a change */ char use_polling; device_t usbctl; @@ -301,18 +302,24 @@ void usb_needs_explore(usbd_device_hand void usb_needs_reattach(usbd_device_handle); void usb_schedsoftintr(struct usbd_bus *); -#define usbd_lock_pipe(p) do { \ - if ((p)->device->bus->lock) { \ +/* + * These macros help while not all host controllers are ported to the MP code. + */ +#define usbd_mutex_enter(m) do { \ + if (m) { \ s = -1; \ - mutex_enter((p)->device->bus->lock); \ + mutex_enter(m); \ } else \ s = splusb(); \ } while (0) -#define usbd_unlock_pipe(p) do { \ - if ((p)->device->bus->lock) { \ +#define usbd_mutex_exit(m) do { \ + if (m) { \ s = -1; \ - mutex_exit((p)->device->bus->lock); \ + mutex_exit(m); \ } else \ splx(s); \ } while (0) + +#define usbd_lock_pipe(p) usbd_mutex_enter((p)->device->bus->lock) +#define usbd_unlock_pipe(p) usbd_mutex_exit((p)->device->bus->lock)