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>