Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Dec 2008 20:54:21 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 154414 for review
Message-ID:  <200812092054.mB9KsLlk067580@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=154414

Change 154414 by jhb@jhb_mutex on 2008/12/09 20:54:19

	Ensure that driver identify routines only get called at the
	driver's pass level.

Affected files ...

.. //depot/projects/multipass/notes#4 edit
.. //depot/projects/multipass/sys/kern/subr_bus.c#3 edit
.. //depot/projects/multipass/sys/sys/bus.h#3 edit

Differences ...

==== //depot/projects/multipass/notes#4 (text+ko) ====

@@ -8,10 +8,13 @@
 - BUS_PASS_BUSSES (10)
   - enumerate busses, bridges usually should be here
 - BUS_PASS_CPUS (20)
-- BUS_PASS_INTERRUPT_CONTROLLERS (30)
-- BUS_PASS_TIMERS (40)
-- will want to start up SMP and schedulers after this point before continuing
-  further, can clear cold as well then
+- BUS_PASS_RESOURCE (30)
+  - resource discovery happens after this pass
+- BUS_PASS_INTERRUPT_CONTROLLERS (40)
+- BUS_PASS_TIMERS (50)
+- BUS_PASS_SCHEDULER (60)
+  - will want to start up SMP and schedulers after this point before continuing
+    further, can clear cold as well then
 - BUS_PASS_DEFAULT (INT_MAX)
 
 Milestones / Todo:
@@ -33,3 +36,34 @@
 + Change root_bus_configure() to raise the pass level to kick off a scan.
 + Don't invoke BUS_PROBE_NOMATCH() until a device fails to match during
   the last pass.
++ Handle identify routines.  bus_generic_probe() only calls identify for
+  drivers at or below the current pass level, so is always suitable to
+  be called from an attach routine, both for early and regular drivers.  It
+  can also be called from an early driver kldload'ed after boot and DTRT.
+  BUS_NEW_PASS() is now responsible for calling the identify routines for
+  any drivers for the current pass (only == current pass).  Right now this
+  is just in bus_generic_new_pass().
+
+Guidelines for Writing an Early Driver:
+---------------------------------------
+- Use bus_generic_new_pass() for 'bus_new_pass' device method in bus_if.m.
+- Use EARLY_DRIVER_MODULE() for attachment to specify pass.
+- If you support being in a kld that can be loaded after boot then your
+  attach routine may need to perform the work of later passes explicitly
+  in its attach routine if bus_current_pass is too high.
+
+Thoughts about Resource Discovery:
+----------------------------------
+- First raise pass to BUS_PASS_RESOURCE via bus_set_pass().
+- Rather than requiring drivers to overload BUS_NEW_PASS() to hook
+  BUS_PASS_RESOURCE(), add a new device_if.h method bus_discover_resources().
+- For the PCI case:
+  - pcibX devices may create resource managers that they sub-allocate to
+    child devices from (though requests from, e.g. ISA devices may need to
+    pass through?).  For ACPI and MP Table we can actually build these
+    resource managers from BIOS info.
+  - For PCI-PCI bridges, we alway use a resource manager that represents the
+    resource windows in the bridge that we sub-allocate to child devices.
+- We will need a way to destroy a resource manager, and something like
+  device_set_desc_copy() where the rman allocates its own copy of the name
+  and frees it on destroy.

==== //depot/projects/multipass/sys/kern/subr_bus.c#3 (text+ko) ====

@@ -3031,6 +3031,17 @@
 	driverlink_t dl;
 
 	TAILQ_FOREACH(dl, &dc->drivers, link) {
+		/*
+		 * If this driver's pass is too high, then ignore it.
+		 * For most drivers in the default pass, this will
+		 * never be true.  For early-pass drivers they will
+		 * only call the identify routines of eligible drivers
+		 * when this routine is called.  Drivers for later
+		 * passes should have their identify routines called
+		 * on early-pass busses during BUS_NEW_PASS().
+		 */
+		if (dl->pass > bus_current_pass)
+				continue;
 		DEVICE_IDENTIFY(dl->driver, dev);
 	}
 
@@ -3260,16 +3271,22 @@
 /**
  * @brief Helper function for implementing BUS_NEW_PASS().
  *
- * This implementing of BUS_NEW_PASS() walks the list of devices for this
- * bus.  If a device is already attached, then it calls BUS_NEW_PASS() on
- * that device.  If the device is not already attached, it attempts to
- * attach a driver to it.
+ * This implementing of BUS_NEW_PASS() first calls the identify
+ * routines for any drivers that probe at the current pass.  Then it
+ * walks the list of devices for this bus.  If a device is already
+ * attached, then it calls BUS_NEW_PASS() on that device.  If the
+ * device is not already attached, it attempts to attach a driver to
+ * it.
  */
 void
 bus_generic_new_pass(device_t dev)
 {
 	device_t child;
 
+	TAILQ_FOREACH(dl, &dc->drivers, link) {
+		if (dl->pass == bus_current_pass)
+			DEVICE_IDENTIFY(dl->driver, dev);
+	}
 	TAILQ_FOREACH(child, &dev->children, link) {
 		if (child->state >= DS_ATTACHED)
 			BUS_NEW_PASS(child);

==== //depot/projects/multipass/sys/sys/bus.h#3 (text+ko) ====

@@ -525,8 +525,10 @@
 #define	BUS_PASS_ROOT		0	/* Used to attach root0. */
 #define	BUS_PASS_BUS		10	/* Busses and bridges. */
 #define	BUS_PASS_CPU		20	/* CPU devices. */
-#define	BUS_PASS_INTERRUPT	30	/* Interrupt controllers. */
-#define	BUS_PASS_TIMER		40	/* Timers and clocks. */
+#define	BUS_PASS_RESOURCE	30	/* Resource discovery. */
+#define	BUS_PASS_INTERRUPT	40	/* Interrupt controllers. */
+#define	BUS_PASS_TIMER		50	/* Timers and clocks. */
+#define	BUS_PASS_SCHEDULER	60	/* Start scheduler. */
 #define	BUS_PASS_DEFAULT	__INT_MAX /* Everything else. */
 
 extern int bus_current_pass;



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