summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2009-03-29 16:45:36 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2009-03-29 16:45:36 +0000
commit388119e64aa8692eb907041b048836dfa912ee66 (patch)
tree4e3595a6d582c14aebf542d27bd1831da6ff635c /sys
parent219278b23d55767a19508bfbf816a59aff614d25 (diff)
Finally fix kernel crash (page fault) when closing bulk devices.
Help from kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/uvideo.c16
1 files changed, 6 insertions, 10 deletions
diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 6fa9763df9e..b73ec910e5c 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.c,v 1.123 2009/03/28 09:18:28 mglocker Exp $ */
+/* $OpenBSD: uvideo.c,v 1.124 2009/03/29 16:45:35 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
@@ -1726,15 +1726,10 @@ uvideo_vs_open(struct uvideo_softc *sc)
void
uvideo_vs_close(struct uvideo_softc *sc)
{
- /*
- * XXX
- * A bulk device will crash the kernel here, because in almost all
- * cases we close the pipe before sc->sc_vs_cur->bulk_running = 0
- * gets noticed in the thread loop of uvideo_vs_start_bulk_thread(),
- * which make it access a closed pipe. We need to fix this
- * properly.
- */
- sc->sc_vs_cur->bulk_running = 0;
+ if (sc->sc_vs_cur->bulk_running == 1) {
+ sc->sc_vs_cur->bulk_running = 0;
+ (void)tsleep(&sc->sc_vs_cur->bulk_running, 0, "vid_close", 0);
+ }
if (sc->sc_vs_cur->pipeh) {
usbd_abort_pipe(sc->sc_vs_cur->pipeh);
@@ -1829,6 +1824,7 @@ uvideo_vs_start_bulk_thread(void *arg)
(void)sc->sc_decode_stream_header(sc,
sc->sc_vs_cur->bxfer.buf, size);
}
+ wakeup(&sc->sc_vs_cur->bulk_running);
kthread_exit(0);
}