PERFORCE change 118675 for review

Hans Petter Selasky hselasky at FreeBSD.org
Mon Apr 23 19:19:22 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118675

Change 118675 by hselasky at hselasky_mini_itx on 2007/04/23 19:18:51

	Make the USB stack smarter by allowing
	NULL pointer arguments to be passed
	to usbd_transfer_start() and
	usbd_transfer_stop(). At the same
	time add some more comments describing
	why.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#21 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#21 (text+ko) ====

@@ -383,7 +383,6 @@
 	while(n_setup--)
 	{
 	    xfer = pxfer[n_setup];
-	    pxfer[n_setup] = NULL;
 
 	    if(xfer)
 	    {
@@ -391,6 +390,27 @@
 		{
 		    mtx_lock(xfer->priv_mtx);
 
+		    /* HINT: when you start/stop a transfer,
+		     * it might be a good idea to directly
+		     * use the "pxfer[]" structure:
+		     *
+		     * usbd_transfer_start(sc->pxfer[0]);
+		     * usbd_transfer_stop(sc->pxfer[0]);
+		     *
+		     * That way, if your code has many parts
+		     * that will not stop running under the
+		     * same lock, in other words "priv_mtx",
+		     * the usbd_transfer_start and
+		     * usbd_transfer_stop functions will
+		     * simply return when they detect a NULL
+		     * pointer argument.
+		     *
+		     * To avoid any races we clear the "pxfer[]"
+		     * pointer while holding the private mutex
+		     * of the driver:
+		     */
+		    pxfer[n_setup] = NULL;
+
 		    usbd_transfer_stop(xfer);
 
 		    /* NOTE: default pipe does not
@@ -400,6 +420,9 @@
 		    xfer->pipe->refcount--;
 
 		    mtx_unlock(xfer->priv_mtx);
+		} else {
+		    /* clear the transfer pointer */
+		    pxfer[n_setup] = NULL;
 		}
 
 		__callout_drain(&(xfer->timeout_handle));
@@ -423,6 +446,8 @@
 
 		    if (info->setup_refcount == 0) {
 
+		        /* wait for any USB callbacks to return */
+
 		        while (info->memory_refcount > 0) {
 			    error = msleep(info, info->usb_mtx, 0, 
 					   "usb_mem_wait", 0);
@@ -708,9 +733,11 @@
 }
 
 /*---------------------------------------------------------------------------*
- *	usbd_transfer_start - start a USB transfer
+ *	usbd_transfer_start - start an USB transfer
  *
- * NOTE: this function can be called any number of times
+ * NOTE: Calling this function more than one time will only
+ *       result in a single transfer start, until the USB transfer
+ *       completes.
  * NOTE: if USBD_SYNCHRONOUS is set in "xfer->flags", then this
  *       function will sleep for transfer completion
  * NOTE: if USBD_USE_POLLING is set in "xfer->flags", then this
@@ -719,6 +746,11 @@
 void
 usbd_transfer_start(struct usbd_xfer *xfer)
 {
+	if (xfer == NULL) {
+	    /* transfer is gone */
+	    return;
+	}
+
 	mtx_assert(xfer->priv_mtx, MA_OWNED);
 
 	if(!(xfer->flags & USBD_DEV_OPEN))
@@ -793,13 +825,19 @@
 }
 
 /*---------------------------------------------------------------------------*
- *	usbd_transfer_stop - stop a USB transfer
+ *	usbd_transfer_stop - stop an USB transfer
  *
- * NOTE: this function can be called any number of times
+ * NOTE: Calling this function more than one time will only
+ *       result in a single transfer stop.
  *---------------------------------------------------------------------------*/
 void
 usbd_transfer_stop(struct usbd_xfer *xfer)
 {
+	if (xfer == NULL) {
+	    /* transfer is gone */
+	    return;
+	}
+
 	mtx_assert(xfer->priv_mtx, MA_OWNED);
 
 	if(xfer->flags & USBD_DEV_OPEN)


More information about the p4-projects mailing list