Module Name:    src
Committed By:   mrg
Date:           Sat Jun  2 08:07:25 UTC 2012

Modified Files:
        src/sys/dev/usb [jmcneill-usbmp]: TODO.usbmp usbdi.c usbdi.h
            usbdi_util.c

Log Message:
convert usbd_{intr,bulk}_transfer() in the USBMP world:
- add a new USBD_SYNCHRONOUS_SIG flag for transfers
- in usbd_transfer(), if USBD_SYNCHRONOUS_SIG is set use cv_wait_sig()
  (or tlseep(xfer, PZERO|PATCH, ...) for the unconverted controllers)
- add a usbd_sync_transfer_sig() front-end to usbd_transfer()
- greatly simplify both usbd_{intr,bulk}_transfer() to just
  usbd_sync_transfer_sig() and usbd_get_xfer_status().

this fixes lockdebug issues where usbd_{intr,bulk}_transfer() where it
taking the pipe lock, when usbd_transfer() would call functions that
expect the pipe lock not to be taken (and try to taken it.)


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.13 -r1.1.2.14 src/sys/dev/usb/TODO.usbmp
cvs rdiff -u -r1.134.2.15 -r1.134.2.16 src/sys/dev/usb/usbdi.c
cvs rdiff -u -r1.80.2.2 -r1.80.2.3 src/sys/dev/usb/usbdi.h
cvs rdiff -u -r1.55.12.7 -r1.55.12.8 src/sys/dev/usb/usbdi_util.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/TODO.usbmp
diff -u src/sys/dev/usb/TODO.usbmp:1.1.2.13 src/sys/dev/usb/TODO.usbmp:1.1.2.14
--- src/sys/dev/usb/TODO.usbmp:1.1.2.13	Sat May 12 21:30:07 2012
+++ src/sys/dev/usb/TODO.usbmp	Sat Jun  2 08:07:25 2012
@@ -1,4 +1,4 @@
-$NetBSD: TODO.usbmp,v 1.1.2.13 2012/05/12 21:30:07 mrg Exp $
+$NetBSD: TODO.usbmp,v 1.1.2.14 2012/06/02 08:07:25 mrg Exp $
 
 
 the majority of the USB MP device interface is documented in usbdivar.h.
@@ -155,7 +155,7 @@ driver testing:		STATUS
   - uyap
   - udsbr
   - ugen		mostly done, testing is a MERGE ISSUE
-  - pseye
+  - pseye		working
   - uvideo
   - auvitek		? (must take kernel lock for scsipi)
   - emdtv		? (must take kernel lock for scsipi)

Index: src/sys/dev/usb/usbdi.c
diff -u src/sys/dev/usb/usbdi.c:1.134.2.15 src/sys/dev/usb/usbdi.c:1.134.2.16
--- src/sys/dev/usb/usbdi.c:1.134.2.15	Tue Mar  6 18:26:48 2012
+++ src/sys/dev/usb/usbdi.c	Sat Jun  2 08:07:25 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi.c,v 1.134.2.15 2012/03/06 18:26:48 mrg Exp $	*/
+/*	$NetBSD: usbdi.c,v 1.134.2.16 2012/06/02 08:07:25 mrg Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.15 2012/03/06 18:26:48 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.16 2012/06/02 08:07:25 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_usb.h"
@@ -322,10 +322,17 @@ usbd_transfer(usbd_xfer_handle xfer)
 		if (pipe->device->bus->use_polling)
 			panic("usbd_transfer: not done");
 
-		if (pipe->device->bus->lock)
-			cv_wait(&xfer->cv, pipe->device->bus->lock);
-		else
-			tsleep(xfer, PRIBIO, "usbsyn", 0);
+		if ((flags & USBD_SYNCHRONOUS_SIG) != 0) {
+			if (pipe->device->bus->lock)
+				cv_wait_sig(&xfer->cv, pipe->device->bus->lock);
+			else
+				tsleep(xfer, PZERO|PCATCH, "usbsyn", 0);
+		} else {
+			if (pipe->device->bus->lock)
+				cv_wait(&xfer->cv, pipe->device->bus->lock);
+			else
+				tsleep(xfer, PRIBIO, "usbsyn", 0);
+		}
 	}
 	usbd_unlock_pipe(pipe);
 	return (xfer->status);
@@ -339,6 +346,14 @@ usbd_sync_transfer(usbd_xfer_handle xfer
 	return (usbd_transfer(xfer));
 }
 
+/* Like usbd_transfer(), but waits for completion and listens for signals. */
+usbd_status
+usbd_sync_transfer_sig(usbd_xfer_handle xfer)
+{
+	xfer->flags |= USBD_SYNCHRONOUS | USBD_SYNCHRONOUS_SIG;
+	return (usbd_transfer(xfer));
+}
+
 void *
 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
 {
@@ -780,7 +795,7 @@ usb_transfer_complete(usbd_xfer_handle x
 
 #ifdef DIAGNOSTIC
 	if (pipe == NULL) {
-		printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
+		printf("usb_transfer_complete: pipe==0, xfer=%p\n", xfer);
 		return;
 	}
 #endif
@@ -831,7 +846,7 @@ usb_transfer_complete(usbd_xfer_handle x
 	xfer->done = 1;
 	if (!xfer->status && xfer->actlen < xfer->length &&
 	    !(xfer->flags & USBD_SHORT_XFER_OK)) {
-		DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
+		DPRINTFN(-1,("usb_transfer_complete: short transfer %d<%d\n",
 			     xfer->actlen, xfer->length));
 		xfer->status = USBD_SHORT_XFER;
 	}

Index: src/sys/dev/usb/usbdi.h
diff -u src/sys/dev/usb/usbdi.h:1.80.2.2 src/sys/dev/usb/usbdi.h:1.80.2.3
--- src/sys/dev/usb/usbdi.h:1.80.2.2	Sun Apr 29 23:05:02 2012
+++ src/sys/dev/usb/usbdi.h	Sat Jun  2 08:07:25 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi.h,v 1.80.2.2 2012/04/29 23:05:02 mrg Exp $	*/
+/*	$NetBSD: usbdi.h,v 1.80.2.3 2012/06/02 08:07:25 mrg Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $	*/
 
 /*
@@ -80,6 +80,8 @@ typedef void (*usbd_callback)(usbd_xfer_
 #define USBD_SYNCHRONOUS	0x02	/* wait for completion */
 /* in usb.h #define USBD_SHORT_XFER_OK	0x04*/	/* allow short reads */
 #define USBD_FORCE_SHORT_XFER	0x08	/* force last short packet on write */
+#define USBD_SYNCHRONOUS_SIG	0x10	/* if waiting for completion,
+					 * also take signals */
 
 #define USBD_NO_TIMEOUT 0
 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -125,6 +127,7 @@ void *usbd_alloc_buffer(usbd_xfer_handle
 void usbd_free_buffer(usbd_xfer_handle);
 void *usbd_get_buffer(usbd_xfer_handle);
 usbd_status usbd_sync_transfer(usbd_xfer_handle);
+usbd_status usbd_sync_transfer_sig(usbd_xfer_handle);
 usbd_status usbd_open_pipe_intr(usbd_interface_handle, u_int8_t,
 				u_int8_t, usbd_pipe_handle *,
 				usbd_private_handle, void *,

Index: src/sys/dev/usb/usbdi_util.c
diff -u src/sys/dev/usb/usbdi_util.c:1.55.12.7 src/sys/dev/usb/usbdi_util.c:1.55.12.8
--- src/sys/dev/usb/usbdi_util.c:1.55.12.7	Tue Mar  6 18:26:48 2012
+++ src/sys/dev/usb/usbdi_util.c	Sat Jun  2 08:07:25 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi_util.c,v 1.55.12.7 2012/03/06 18:26:48 mrg Exp $	*/
+/*	$NetBSD: usbdi_util.c,v 1.55.12.8 2012/06/02 08:07:25 mrg Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.55.12.7 2012/03/06 18:26:48 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.55.12.8 2012/06/02 08:07:25 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -434,28 +434,13 @@ usbd_bulk_transfer(usbd_xfer_handle xfer
 		   u_int32_t *size, const char *lbl)
 {
 	usbd_status err;
-	int s, error;
 
 	usbd_setup_xfer(xfer, pipe, 0, buf, *size,
 			flags, timeout, usbd_bulk_transfer_cb);
 	DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
-	usbd_lock_pipe(pipe);	/* don't want callback until block */
-	err = usbd_transfer(xfer);
-	if (err != USBD_IN_PROGRESS) {
-		usbd_unlock_pipe(pipe);
-		return (err);
-	}
-	if (pipe->device->bus->lock)
-		error = cv_wait_sig(&xfer->cv, pipe->device->bus->lock);
-	else
-		error = tsleep(xfer, PZERO | PCATCH, lbl, 0); /* XXXSMP ok */
-	usbd_unlock_pipe(pipe);
-	if (error) {
-		DPRINTF(("usbd_bulk_transfer: wait=%d\n", error));
-		usbd_abort_pipe(pipe);
-		return (USBD_INTERRUPTED);
-	}
-	usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
+
+	err = usbd_sync_transfer_sig(xfer);
+	usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
 	DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
 	if (err) {
 		DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
@@ -483,28 +468,12 @@ usbd_intr_transfer(usbd_xfer_handle xfer
 		   u_int32_t *size, const char *lbl)
 {
 	usbd_status err;
-	int s, error;
 
 	usbd_setup_xfer(xfer, pipe, 0, buf, *size,
 			flags, timeout, usbd_intr_transfer_cb);
 	DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
-	usbd_lock_pipe(pipe);	/* don't want callback until block */
-	err = usbd_transfer(xfer);
-	if (err != USBD_IN_PROGRESS) {
-		usbd_unlock_pipe(pipe);
-		return (err);
-	}
-	if (pipe->device->bus->lock)
-		error = cv_wait_sig(&xfer->cv, pipe->device->bus->lock);
-	else
-		error = tsleep(xfer, PZERO | PCATCH, lbl, 0); /* XXXSMP ok */
-	usbd_unlock_pipe(pipe);
-	if (error) {
-		DPRINTF(("usbd_intr_transfer: wait=%d\n", error));
-		usbd_abort_pipe(pipe);
-		return (USBD_INTERRUPTED);
-	}
-	usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
+	err = usbd_sync_transfer_sig(xfer);
+	usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
 	DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
 	if (err) {
 		DPRINTF(("usbd_intr_transfer: error=%d\n", err));

Reply via email to