PERFORCE change 154414 for review
John Baldwin
jhb at FreeBSD.org
Tue Dec 9 12:54:22 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=154414
Change 154414 by jhb at 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;
More information about the p4-projects
mailing list