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)