Module Name:    src
Committed By:   mrg
Date:           Tue Dec  6 02:10:02 UTC 2011

Modified Files:
        src/sys/dev/usb [jmcneill-usbmp]: ehci.c ohci.c usb.c

Log Message:
need to ensure kpreempt_disable() for softint_schedule().

fix the locking in ohci_timeout_task(), ohci_device_isoc_start(),
ohci_device_isoc_abort() and ohci_device_isoc_close().

uaudio(4) can still play with these, but mixerctl -a against it will
hang the writer.  however, mixerctl continues to run in a tight loop
and the system isn't soft-locked up at this point, an advance from
how it is in -current.


To generate a diff of this commit:
cvs rdiff -u -r1.181.6.2 -r1.181.6.3 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.218.6.2 -r1.218.6.3 src/sys/dev/usb/ohci.c
cvs rdiff -u -r1.125.6.1 -r1.125.6.2 src/sys/dev/usb/usb.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.181.6.2 src/sys/dev/usb/ehci.c:1.181.6.3
--- src/sys/dev/usb/ehci.c:1.181.6.2	Sun Dec  4 19:22:56 2011
+++ src/sys/dev/usb/ehci.c	Tue Dec  6 02:10:01 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci.c,v 1.181.6.2 2011/12/04 19:22:56 jmcneill Exp $ */
+/*	$NetBSD: ehci.c,v 1.181.6.3 2011/12/06 02:10:01 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.2 2011/12/04 19:22:56 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.181.6.3 2011/12/06 02:10:01 mrg Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -652,7 +652,9 @@ ehci_intr1(ehci_softc_t *sc)
 	sc->sc_bus.no_intrs++;
 	if (eintrs & EHCI_STS_IAA) {
 		DPRINTF(("ehci_intr1: door bell\n"));
+		kpreempt_disable();
 		softint_schedule(sc->sc_doorbell_si);
+		kpreempt_enable();
 		eintrs &= ~EHCI_STS_IAA;
 	}
 	if (eintrs & (EHCI_STS_INT | EHCI_STS_ERRINT)) {
@@ -668,7 +670,9 @@ ehci_intr1(ehci_softc_t *sc)
 		/* XXX what else */
 	}
 	if (eintrs & EHCI_STS_PCD) {
+		kpreempt_disable();
 		softint_schedule(sc->sc_pcd_si);
+		kpreempt_enable();
 		eintrs &= ~EHCI_STS_PCD;
 	}
 

Index: src/sys/dev/usb/ohci.c
diff -u src/sys/dev/usb/ohci.c:1.218.6.2 src/sys/dev/usb/ohci.c:1.218.6.3
--- src/sys/dev/usb/ohci.c:1.218.6.2	Sun Dec  4 21:02:27 2011
+++ src/sys/dev/usb/ohci.c	Tue Dec  6 02:10:01 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohci.c,v 1.218.6.2 2011/12/04 21:02:27 jmcneill Exp $	*/
+/*	$NetBSD: ohci.c,v 1.218.6.3 2011/12/06 02:10:01 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.2 2011/12/04 21:02:27 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.3 2011/12/06 02:10:01 mrg Exp $");
 
 #include "opt_usb.h"
 
@@ -2020,14 +2020,10 @@ void
 ohci_timeout_task(void *addr)
 {
 	usbd_xfer_handle xfer = addr;
-	ohci_softc_t *sc = xfer->pipe->device->bus->hci_private;
 
 	DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer));
 
-	KASSERT(mutex_owned(&sc->sc_lock));
-	//mutex_enter(&sc->sc_lock);
 	ohci_abort_xfer(xfer, USBD_TIMEOUT);
-	//mutex_exit(&sc->sc_lock);
 }
 
 #ifdef OHCI_DEBUG
@@ -3540,6 +3536,8 @@ ohci_device_isoc_start(usbd_xfer_handle 
 
 	/* XXX anything to do? */
 
+	mutex_exit(&sc->sc_lock);
+
 	return (USBD_IN_PROGRESS);
 }
 
@@ -3551,9 +3549,9 @@ ohci_device_isoc_abort(usbd_xfer_handle 
 	ohci_soft_ed_t *sed;
 	ohci_soft_itd_t *sitd;
 
-	DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer));
+	DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p lock=%p\n", xfer, &sc->sc_lock));
 
-	KASSERT(mutex_owned(&sc->sc_lock));
+	mutex_enter(&sc->sc_lock);
 
 	/* Transfer is already done. */
 	if (xfer->status != USBD_NOT_STARTED &&
@@ -3635,9 +3633,11 @@ ohci_device_isoc_close(usbd_pipe_handle 
 	ohci_softc_t *sc = pipe->device->bus->hci_private;
 
 	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
+	mutex_exit(&sc->sc_lock);
 	ohci_free_sitd(sc, opipe->tail.itd);
 }

Index: src/sys/dev/usb/usb.c
diff -u src/sys/dev/usb/usb.c:1.125.6.1 src/sys/dev/usb/usb.c:1.125.6.2
--- src/sys/dev/usb/usb.c:1.125.6.1	Sun Dec  4 13:23:17 2011
+++ src/sys/dev/usb/usb.c	Tue Dec  6 02:10:01 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb.c,v 1.125.6.1 2011/12/04 13:23:17 jmcneill Exp $	*/
+/*	$NetBSD: usb.c,v 1.125.6.2 2011/12/06 02:10:01 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.1 2011/12/04 13:23:17 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.2 2011/12/06 02:10:01 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_usb.h"
@@ -890,7 +890,9 @@ usb_add_event(int type, struct usb_event
 	wakeup(&usb_events);
 	selnotify(&usb_selevent, 0, 0);
 	if (usb_async_proc != NULL) {
+		kpreempt_disable();
 		softint_schedule(usb_async_sih);
+		kpreempt_enable();
 	}
 	splx(s);
 }
@@ -913,7 +915,9 @@ usb_schedsoftintr(usbd_bus_handle bus)
 	if (bus->use_polling) {
 		bus->methods->soft_intr(bus);
 	} else {
+		kpreempt_disable();
 		softint_schedule(bus->soft);
+		kpreempt_enable();
 	}
 }
 

Reply via email to