PERFORCE change 163254 for review

Hans Petter Selasky hselasky at FreeBSD.org
Mon Jun 1 12:31:42 UTC 2009


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

Change 163254 by hselasky at hselasky_laptop001 on 2009/06/01 12:30:53

	
	USB CORE: Fix multithread issue where
	the is_uref variable was not set and cleared
	properly in the CDEV private data.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_dev.c#25 edit

Differences ...

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

@@ -169,21 +169,23 @@
 	cpd->bus = devclass_get_softc(usb2_devclass_ptr, cpd->bus_index);
 	if (cpd->bus == NULL) {
 		DPRINTFN(2, "no bus at %u\n", cpd->bus_index);
+		need_uref = 0;
 		goto error;
 	}
 	cpd->udev = cpd->bus->devices[cpd->dev_index];
 	if (cpd->udev == NULL) {
 		DPRINTFN(2, "no device at %u\n", cpd->dev_index);
+		need_uref = 0;
 		goto error;
 	}
 	if (cpd->udev->refcount == USB_DEV_REF_MAX) {
 		DPRINTFN(2, "no dev ref\n");
+		need_uref = 0;
 		goto error;
 	}
 	if (need_uref) {
 		DPRINTFN(2, "ref udev - needed\n");
 		cpd->udev->refcount++;
-		cpd->is_uref = 1;
 
 		mtx_unlock(&usb2_ref_lock);
 
@@ -194,6 +196,11 @@
 		sx_xlock(cpd->udev->default_sx + 1);
 
 		mtx_lock(&usb2_ref_lock);
+
+		/* 
+		 * Set "is_uref" after grabbing the default SX lock
+		 */
+		cpd->is_uref = 1;
 	}
 
 	/* check if we are doing an open */
@@ -258,18 +265,18 @@
 	}
 	mtx_unlock(&usb2_ref_lock);
 
-	if (cpd->is_uref) {
+	if (need_uref) {
 		mtx_lock(&Giant);	/* XXX */
 	}
 	return (0);
 
 error:
-	if (cpd->is_uref) {
+	if (need_uref) {
+		cpd->is_uref = 0;
 		sx_unlock(cpd->udev->default_sx + 1);
 		if (--(cpd->udev->refcount) == 0) {
 			usb2_cv_signal(cpd->udev->default_cv + 1);
 		}
-		cpd->is_uref = 0;
 	}
 	mtx_unlock(&usb2_ref_lock);
 	DPRINTFN(2, "fail\n");
@@ -289,10 +296,14 @@
 static usb_error_t
 usb2_usb_ref_device(struct usb_cdev_privdata *cpd)
 {
+	uint8_t is_uref;
+
+	is_uref = cpd->is_uref && sx_xlocked(cpd->udev->default_sx + 1);
+
 	/*
 	 * Check if we already got an USB reference on this location:
 	 */
-	if (cpd->is_uref)
+	if (is_uref)
 		return (0);		/* success */
 
 	/*
@@ -313,7 +324,12 @@
 void
 usb2_unref_device(struct usb_cdev_privdata *cpd)
 {
-	if (cpd->is_uref) {
+	uint8_t is_uref;
+
+	is_uref = cpd->is_uref && sx_xlocked(cpd->udev->default_sx + 1);
+
+	if (is_uref) {
+		cpd->is_uref = 0;
 		mtx_unlock(&Giant);	/* XXX */
 		sx_unlock(cpd->udev->default_sx + 1);
 	}
@@ -330,11 +346,10 @@
 		}
 		cpd->is_write = 0;
 	}
-	if (cpd->is_uref) {
+	if (is_uref) {
 		if (--(cpd->udev->refcount) == 0) {
 			usb2_cv_signal(cpd->udev->default_cv + 1);
 		}
-		cpd->is_uref = 0;
 	}
 	mtx_unlock(&usb2_ref_lock);
 }


More information about the p4-projects mailing list