Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Apr 2012 20:57:41 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234152 - in head/sys: kern sys
Message-ID:  <201204112057.q3BKvfoA095440@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed Apr 11 20:57:41 2012
New Revision: 234152
URL: http://svn.freebsd.org/changeset/base/234152

Log:
  Allow device_busy() and device_unbusy() to be invoked while a device is
  being attached.  This is implemented by adding a new DS_ATTACHING state
  while a device's DEVICE_ATTACH() method is being invoked.  A driver is
  required to not fail an attach of a busy device.  The device's state will
  be promoted to DS_BUSY rather than DS_ACTIVE() if the device was marked
  busy during DEVICE_ATTACH().
  
  Reviewed by:	kib
  MFC after:	1 week

Modified:
  head/sys/kern/subr_bus.c
  head/sys/sys/bus.h

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c	Wed Apr 11 20:55:21 2012	(r234151)
+++ head/sys/kern/subr_bus.c	Wed Apr 11 20:57:41 2012	(r234152)
@@ -2472,12 +2472,13 @@ device_disable(device_t dev)
 void
 device_busy(device_t dev)
 {
-	if (dev->state < DS_ATTACHED)
+	if (dev->state < DS_ATTACHING)
 		panic("device_busy: called for unattached device");
 	if (dev->busy == 0 && dev->parent)
 		device_busy(dev->parent);
 	dev->busy++;
-	dev->state = DS_BUSY;
+	if (dev->state == DS_ATTACHED)
+		dev->state = DS_BUSY;
 }
 
 /**
@@ -2486,14 +2487,16 @@ device_busy(device_t dev)
 void
 device_unbusy(device_t dev)
 {
-	if (dev->state != DS_BUSY)
+	if (dev->busy != 0 && dev->state != DS_BUSY &&
+	    dev->state != DS_ATTACHING)
 		panic("device_unbusy: called for non-busy device %s",
 		    device_get_nameunit(dev));
 	dev->busy--;
 	if (dev->busy == 0) {
 		if (dev->parent)
 			device_unbusy(dev->parent);
-		dev->state = DS_ATTACHED;
+		if (dev->state == DS_BUSY)
+			dev->state = DS_ATTACHED;
 	}
 }
 
@@ -2729,6 +2732,7 @@ device_attach(device_t dev)
 	device_sysctl_init(dev);
 	if (!device_is_quiet(dev))
 		device_print_child(dev->parent, dev);
+	dev->state = DS_ATTACHING;
 	if ((error = DEVICE_ATTACH(dev)) != 0) {
 		printf("device_attach: %s%d attach returned %d\n",
 		    dev->driver->name, dev->unit, error);
@@ -2736,11 +2740,15 @@ device_attach(device_t dev)
 			devclass_delete_device(dev->devclass, dev);
 		(void)device_set_driver(dev, NULL);
 		device_sysctl_fini(dev);
+		KASSERT(dev->busy == 0, ("attach failed but busy"));
 		dev->state = DS_NOTPRESENT;
 		return (error);
 	}
 	device_sysctl_update(dev);
-	dev->state = DS_ATTACHED;
+	if (dev->busy)
+		dev->state = DS_BUSY;
+	else
+		dev->state = DS_ATTACHED;
 	dev->flags &= ~DF_DONENOMATCH;
 	devadded(dev);
 	return (0);

Modified: head/sys/sys/bus.h
==============================================================================
--- head/sys/sys/bus.h	Wed Apr 11 20:55:21 2012	(r234151)
+++ head/sys/sys/bus.h	Wed Apr 11 20:57:41 2012	(r234152)
@@ -52,6 +52,7 @@ struct u_businfo {
 typedef enum device_state {
 	DS_NOTPRESENT = 10,		/**< @brief not probed or probe failed */
 	DS_ALIVE = 20,			/**< @brief probe succeeded */
+	DS_ATTACHING = 25,		/**< @brief currently attaching */
 	DS_ATTACHED = 30,		/**< @brief attach method called */
 	DS_BUSY = 40			/**< @brief device is open */
 } device_state_t;



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