next up previous
Next: Multiple-Pass Proposal Up: Multiple Passes of the Previous: Introduction

Subsections

Some Tricky Problems

One of the design goals of ``new-bus'' is that all devices in the system are probed and attached to drivers in a single pass of the device tree during boot. Rather than having the device driver support code automatically probe new devices as they are added, ``new-bus'' requires bus drivers (i.e. any device that creates children devices) to explicitly probe and attach any devices it creates during its attach routine. While this single-pass system has worked relatively well so far, there are some specific problems that it does not easily solve.

Low-level Hardware

Many hardware devices provide resources used by other hardware devices. For example, a bridge may provide ranges of address space for devices on a bus, or interrupt controllers may map device interrupt line assertions to CPU interrupt events. A device driver depends on these resources being available and usable while it is managing a device. Currently, these low-level devices are not always managed within the ``new-bus'' framework.

Some devices such as bridges are always probed before the devices that depend on them. Those devices are easily managed as ``new-bus'' devices. Other devices are not always probed first, however.

On x86 machines the 8259A interrupt controllers are generally enumerated as devices on the ISA bus that is the child of a PCI-ISA bridge. The PCI-ISA bridge is normally near the logical ``end'' of its parent PCI bus. It is very common for PCI devices that need interrupt resources to probe and attach before the ISA bus in these systems. The x86 platforms work around this by setting up interrupt controllers in platform-specific code that does not use ``new-bus'' devices. This code uses machine-dependent APIs to setup interrupt handlers and access I/O resources. Later during the ``new-bus'' device probe, dummy device drivers attach to the 8259A interrupt controller devices.

The ACPI bus driver uses a hack to probe certain devices earlier than others. To provide this, the ACPI bus driver knows the PnP IDs of specific ``special'' devices and inserts those devices earlier in its list of children devices to ensure they are probed before other devices. However, this is hacky as special knowledge about children devices belongs in the device drivers for those devices, not in the parent bus.

Resource Discovery and Management

One of the tasks of a device driver framework is to distribute low-level resources among devices. Some devices, such as non-PnP ISA devices, have a fixed set of hard-coded resources. For these devices, resource management consists of reserving those resources so that other devices do not try to use them. Other devices are more complex. They have fully configurable resources that may be assigned by system software. An example of this class of device is a PCI device.

Currently, FreeBSD relies on the system firmware to initialize most of the resources for PCI devices. This has improved in recent years as FreeBSD can now route PCI interrupts and it can assign resources to a device if the parent bus has available resources of the requested type. However, there are still some cases that are not handled.

One specific case involves allocating resources for devices behind a PCI-PCI bridge. Currently, if a device requests a memory or I/O port resource and there is not available room in the parent bridge's existing resource windows, then FreeBSD does not try to grow the resource window. There are some simple cases that could be solved in the current system. First, if the bridge has no window at all then an arbitrary resource range can be allocated from the parent. Second, if the bridge is able to extend its existing window it could use that extension to satisfy the original request. However, in many cases the request to extend the window will fail because the adjacent resource range is already assigned to another device. Moving resources for a device with an active device driver would be error prone. One way to handle this would be to walk the PCI device tree before any devices have started using resources to determine the requirements of all the devices and bridges. Appropriate ranges of resources could then be assigned to each PCI bus behind a PCI-PCI bridge possibly adjusting the ranges set by the firmware if needed.

Boot vs Non-boot Device Probing

Device drivers may attach to devices in two different environments. The first environment is the single pass of the device tree during boot. The second environment is after the system has booted and is fully initialized. This latter environment is used by drivers that are loaded via kldload(8) [5] after boot.

The boot time environment has several restrictions. Prior to FreeBSD 5.0, interrupts were not enabled until later in the boot process, so any drivers that needed to perform more complicated actions using interrupts had to defer that work. Even though interrupts are now enabled during this pass in recent versions of FreeBSD, the thread scheduler is not sufficiently initialized to allow threads to sleep while waiting for an interrupt. In addition, only one CPU is active and performing work during this time.

As a consequence of these restrictions, device drivers that need to perform tasks requiring interrupts when attaching to hardware must handle deferring this work. Although the config_intrconfighook(9) [4] API provides this functionality in a way that works in both environments, it still requires extra work in the driver to use. Having a more unified environment could simplify device drivers.

One of the requirements of the thread scheduler is the ability to provide time outs on sleep requests. This requires some sort of interrupt to fire when a time out request expires. Some platforms provide this via an interrupt from a timer device. For these platforms, the thread scheduler cannot be started until the timer device has been attached.


next up previous
Next: Multiple-Pass Proposal Up: Multiple Passes of the Previous: Introduction