Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/usb/usbdi.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/usb/usbdi.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.134 retrieving revision 1.134.2.5 diff -u -p -r1.134 -r1.134.2.5 --- src/sys/dev/usb/usbdi.c 2011/11/27 03:25:00 1.134 +++ src/sys/dev/usb/usbdi.c 2011/12/09 01:53:00 1.134.2.5 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.134 2011/11/27 03:25:00 jmcneill 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 -__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134 2011/11/27 03:25:00 jmcneill 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,8 @@ usbd_open_pipe_intr(usbd_interface_handl usbd_status usbd_close_pipe(usbd_pipe_handle pipe) { + int s; + #ifdef DIAGNOSTIC if (pipe == NULL) { printf("usbd_close_pipe: pipe==NULL\n"); @@ -236,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); @@ -261,8 +269,6 @@ usbd_transfer(usbd_xfer_handle xfer) DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%#x, pipe=%p, running=%d\n", xfer, xfer->flags, pipe, pipe->running)); - KASSERT(KERNEL_LOCKED_P()); - #ifdef USB_DEBUG if (usbdebug > 5) usbd_dump_queue(pipe); @@ -312,13 +318,17 @@ usbd_transfer(usbd_xfer_handle xfer) /* Sync transfer, wait for completion. */ if (err != USBD_IN_PROGRESS) return (err); - s = splusb(); + usbd_lock_pipe(pipe); if (!xfer->done) { if (pipe->device->bus->use_polling) panic("usbd_transfer: not done"); - tsleep(xfer, PRIBIO, "usbsyn", 0); + + if (pipe->device->bus->lock) + cv_wait(&xfer->cv, pipe->device->bus->lock); + else + tsleep(xfer, PRIBIO, "usbsyn", 0); } - splx(s); + usbd_unlock_pipe(pipe); return (xfer->status); } @@ -378,6 +388,8 @@ usbd_alloc_xfer(usbd_device_handle dev) return (NULL); xfer->device = dev; callout_init(&xfer->timeout_handle, 0); + cv_init(&xfer->cv, "usbxfer"); + cv_init(&xfer->hccv, "usbhcxfer"); DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer)); return (xfer); } @@ -394,6 +406,8 @@ usbd_free_xfer(usbd_xfer_handle xfer) printf("usbd_free_xfer: timout_handle pending"); } #endif + cv_destroy(&xfer->cv); + cv_destroy(&xfer->hccv); xfer->device->bus->methods->freex(xfer->device->bus, xfer); return (USBD_NORMAL_COMPLETION); } @@ -531,9 +545,9 @@ usbd_abort_pipe(usbd_pipe_handle pipe) return (USBD_NORMAL_COMPLETION); } #endif - s = splusb(); + usbd_lock_pipe(pipe); err = usbd_ar_pipe(pipe); - splx(s); + usbd_unlock_pipe(pipe); if (pipe->intrxfer != intrxfer) usbd_free_xfer(intrxfer); return (err); @@ -721,7 +735,7 @@ usbd_ar_pipe(usbd_pipe_handle pipe) { usbd_xfer_handle xfer; - SPLUSBCHECK; + KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); #ifdef USB_DEBUG @@ -734,7 +748,11 @@ usbd_ar_pipe(usbd_pipe_handle pipe) DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", pipe, xfer, pipe->methods)); /* Make the HC abort it (and invoke the callback). */ + if (pipe->device->bus->lock) + mutex_exit(pipe->device->bus->lock); pipe->methods->abort(xfer); + if (pipe->device->bus->lock) + mutex_enter(pipe->device->bus->lock); /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ } pipe->aborting = 0; @@ -752,12 +770,10 @@ usb_transfer_complete(usbd_xfer_handle x xfer->status == USBD_TIMEOUT; int repeat, polling; - SPLUSBCHECK; - DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); - KASSERT(KERNEL_LOCKED_P()); + KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); #ifdef DIAGNOSTIC if (xfer->busy_free != XFER_ONQU) { @@ -825,17 +841,31 @@ usb_transfer_complete(usbd_xfer_handle x } if (repeat) { - if (xfer->callback) + if (xfer->callback) { + if (pipe->device->bus->lock) + mutex_exit(pipe->device->bus->lock); xfer->callback(xfer, xfer->priv, xfer->status); + if (pipe->device->bus->lock) + mutex_enter(pipe->device->bus->lock); + } pipe->methods->done(xfer); } else { pipe->methods->done(xfer); - if (xfer->callback) + if (xfer->callback) { + if (pipe->device->bus->lock) + mutex_exit(pipe->device->bus->lock); xfer->callback(xfer, xfer->priv, xfer->status); + if (pipe->device->bus->lock) + mutex_enter(pipe->device->bus->lock); + } } - if (sync && !polling) - wakeup(xfer); + if (sync && !polling) { + if (pipe->device->bus->lock) + cv_broadcast(&xfer->cv); + else + wakeup(xfer); + } if (!repeat) { /* XXX should we stop the queue on all errors? */ @@ -856,7 +886,7 @@ usb_insert_transfer(usbd_xfer_handle xfe DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", pipe, pipe->running, xfer->timeout)); - KASSERT(KERNEL_LOCKED_P()); + KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); #ifdef DIAGNOSTIC if (xfer->busy_free != XFER_BUSY) { @@ -885,7 +915,7 @@ usbd_start_next(usbd_pipe_handle pipe) usbd_xfer_handle xfer; usbd_status err; - SPLUSBCHECK; + KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); #ifdef DIAGNOSTIC if (pipe == NULL) { @@ -898,13 +928,19 @@ usbd_start_next(usbd_pipe_handle pipe) } #endif + KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); + /* Get next request in queue. */ xfer = SIMPLEQ_FIRST(&pipe->queue); DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); if (xfer == NULL) { pipe->running = 0; } else { + if (pipe->device->bus->lock) + mutex_exit(pipe->device->bus->lock); err = pipe->methods->start(xfer); + if (pipe->device->bus->lock) + mutex_enter(pipe->device->bus->lock); if (err != USBD_IN_PROGRESS) { printf("usbd_start_next: error=%d\n", err); pipe->running = 0;