Device Drivers Best Practice
Garrett D'Amore
gdamore at sun.com
Wed Aug 27 13:05:10 PDT 2008
During today's PSARC meeting, we talked about best practices. One of
the ones that seemed pretty stale and incomplete was the one for device
drivers (see
http://www.opensolaris.org/os/community/arc/bestpractices/bp-device-drivers/
)
So I've undertaken to write a replacement. Here's a draft. Note that
this is not in the format for BPs. We can correct that later -- mostly
I want to offer this up for a general review/comment/feedback at this
point, and once we have the content mostly stable, I'll submit a new
case for it.
So, here's what I have. Some of the items listed below may never have
been expressed in any other document before:
Device Drivers Best Practices
-----------------------------
1. DDI conformance. Device drivers for bundled device drivers SHOULD
adhere to the documented DDI, using only header files, functions,
macros,
structures, and fields that are documented. Note that this precludes
taking the sizeof() certain structures (struct msgb, struct datab,
struct
buf) which are intended to be dynamically allocated. Unbundled device
drivers MUST adhere to the documented DDI, or obtain contracts for any
exceptions required.
2. Proper use of bus/device type specific APIs where applicable. Drivers
SHOULD, when possible, use the latest driver frameworks for certain
types of driver, rather than reimplementing common functionality. For
example, NIC drivers should use the GLD, and SCSI drivers should use the
SCSA framework and USB drivers should use the USB framework.
3. Independence from firmware initialization. Device drivers should not
depend on firmware to initialize devices. While certain portions of
the device may be initialized by OS or BIOS (assignment of PCI
addresses to BARs for example), device drivers should not rely on
firmware to perform any device specific initialization.
4. Support for DDI_SUSPEND and DDI_RESUME. Device drivers must properly
support DDI_SUSPEND and DDI_RESUME, including dealing with a potential
loss of power in between. Note that system firmware may not execute
on resume, so adherence to #3 above will help greatly. Pseudo-drivers
generally don't have to worry about this, and certain kinds of hardware
drivers may be able to rely on their bus parents to properly shutdown
the device.
5. Support for quiesce(9e). In order to facilitate fast-reboot,
drivers should
support the quiesce(9e) DDI entry point. (Not applicable to Solaris
10 or
earlier.)
6. Support for power management. If possible, devices should support
fine grained power management to reduce overall power consumption on
the platform. See power(9e).
7. Portability. Device drivers should avoid assumptions about the
platform they are to run on. A driver should be coded to operate
properly on either SPARC or x86 CPUs. Drivers should not make
assumptions
about the cache, endian, or word size attributes of the host
platform, and
proerly make use of Solaris interfaces such as ddi_dma_sync(9f),
ddi_get32(9f), etc.
8. MP safety. All device drivers must be MP-hot. That is, they must
assume
that entry points and interrupts can all run synchronously, and make use
of synchronization guards (mutex_enter(9f) or similar) to ensure correct
operation.
9. Fault tolerance. Device drivers MUST NEVER panic in response to bad
data received from a source outside of the kernel address space. That
means that data received from a physical device (disk, network, etc.)
must be validated before used in the kernel, as well as data that comes
from user-space. Device drivers should use watchdogs or similar to
guard
against device failure. Device drivers should make use of FMA
interfaces
to handle and report fault conditions.
10. Userland interaction. Device drivers that interact with userland must
be able to deal with either 32-bit or 64-bit applications, performing
any word size conversions as necessary. (Note that no conversion is
necessary when the kernel is running in 32-bit mode.) See
ddi_get_model(9F).
11. Avoiding polling. Drivers should avoid polling whenever possible,
particularly in long running situations. Polling prevents the CPU
from reaching idle state, and increases power consumption for the
entire platform.
12. Do not depend on the system clock rate. The value of HZ can be
different
across reboots. drv_usectohz(9f) can be used if an absolute time is
required.
13. Minimize time running in interrupt context. This is a general guideline
for all device drivers.
14. Avoid use of custom tracing or debugging facilities. Use DTrace
instead.
15. Observability. Drivers SHOULD properly report their operation via
the appropriate kstat(9s)'s for their driver type. This includes
correct accounting of I/O times (kstat_io(9s)) and interrupts
(kstat_intr(9s)).
16. Proper support for dynamic loading & unloading. Device drivers must
support being modunload(1M)'ed through correct support for _fini(9e).
This also means that drivers must support detach(9e) properly.
17. Proper support for hotplug where applicable. A driver for a removable
system peripheral must support hot insertion and removal. Via
attach(9e) and detach(9e). Note that PCI and PCI express busses are
hotpluggable on some platforms.
More information about the opensolaris-arc
mailing list