Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Aug 2011 15:12:53 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r225038 - head/sys/dev/usb
Message-ID:  <201108201512.p7KFCrn1057152@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Sat Aug 20 15:12:53 2011
New Revision: 225038
URL: http://svn.freebsd.org/changeset/base/225038

Log:
  Fix for recursive locking in usb_close() after change 224777.
  
  Approved by:    re (kib)
  MFC after:      3 days
  Reported by:	kwm @

Modified:
  head/sys/dev/usb/usb_dev.c

Modified: head/sys/dev/usb/usb_dev.c
==============================================================================
--- head/sys/dev/usb/usb_dev.c	Sat Aug 20 14:21:32 2011	(r225037)
+++ head/sys/dev/usb/usb_dev.c	Sat Aug 20 15:12:53 2011	(r225038)
@@ -911,10 +911,23 @@ usb_close(void *arg)
 
 	DPRINTFN(2, "cpd=%p\n", cpd);
 
-	err = usb_ref_device(cpd, &refs, 1);
-	if (err) {
-		free(cpd, M_USBDEV);
-		return;
+	err = usb_ref_device(cpd, &refs, 0);
+	if (err)
+		goto done;
+
+	/*
+	 * If this function is not called directly from the root HUB
+	 * thread, there is usually a need to lock the enumeration
+	 * lock. Check this.
+	 */
+	if (!usbd_enum_is_locked(cpd->udev)) {
+
+		DPRINTFN(2, "Locking enumeration\n");
+
+		/* reference device */
+		err = usb_usb_ref_device(cpd, &refs);
+		if (err)
+			goto done;
 	}
 	if (cpd->fflags & FREAD) {
 		usb_fifo_close(refs.rxfifo, cpd->fflags);
@@ -922,10 +935,9 @@ usb_close(void *arg)
 	if (cpd->fflags & FWRITE) {
 		usb_fifo_close(refs.txfifo, cpd->fflags);
 	}
-
 	usb_unref_device(cpd, &refs);
+done:
 	free(cpd, M_USBDEV);
-	return;
 }
 
 static void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108201512.p7KFCrn1057152>