| The Linux Kernel Device Model | |
| Patrick Mochel <mochel@digitalimplant.org> | |
| Drafted 26 August 2002 | |
| Updated 31 January 2006 | |
| Overview | |
| ~~~~~~~~ | |
| The Linux Kernel Driver Model is a unification of all the disparate driver | |
| models that were previously used in the kernel. It is intended to augment the | |
| bus-specific drivers for bridges and devices by consolidating a set of data | |
| and operations into globally accessible data structures. | |
| Traditional driver models implemented some sort of tree-like structure | |
| (sometimes just a list) for the devices they control. There wasn't any | |
| uniformity across the different bus types. | |
| The current driver model provides a common, uniform data model for describing | |
| a bus and the devices that can appear under the bus. The unified bus | |
| model includes a set of common attributes which all busses carry, and a set | |
| of common callbacks, such as device discovery during bus probing, bus | |
| shutdown, bus power management, etc. | |
| The common device and bridge interface reflects the goals of the modern | |
| computer: namely the ability to do seamless device "plug and play", power | |
| management, and hot plug. In particular, the model dictated by Intel and | |
| Microsoft (namely ACPI) ensures that almost every device on almost any bus | |
| on an x86-compatible system can work within this paradigm. Of course, | |
| not every bus is able to support all such operations, although most | |
| buses support most of those operations. | |
| Downstream Access | |
| ~~~~~~~~~~~~~~~~~ | |
| Common data fields have been moved out of individual bus layers into a common | |
| data structure. These fields must still be accessed by the bus layers, | |
| and sometimes by the device-specific drivers. | |
| Other bus layers are encouraged to do what has been done for the PCI layer. | |
| struct pci_dev now looks like this: | |
| struct pci_dev { | |
| ... | |
| struct device dev; /* Generic device interface */ | |
| ... | |
| }; | |
| Note first that the struct device dev within the struct pci_dev is | |
| statically allocated. This means only one allocation on device discovery. | |
| Note also that that struct device dev is not necessarily defined at the | |
| front of the pci_dev structure. This is to make people think about what | |
| they're doing when switching between the bus driver and the global driver, | |
| and to discourage meaningless and incorrect casts between the two. | |
| The PCI bus layer freely accesses the fields of struct device. It knows about | |
| the structure of struct pci_dev, and it should know the structure of struct | |
| device. Individual PCI device drivers that have been converted to the current | |
| driver model generally do not and should not touch the fields of struct device, | |
| unless there is a compelling reason to do so. | |
| The above abstraction prevents unnecessary pain during transitional phases. | |
| If it were not done this way, then when a field was renamed or removed, every | |
| downstream driver would break. On the other hand, if only the bus layer | |
| (and not the device layer) accesses the struct device, it is only the bus | |
| layer that needs to change. | |
| User Interface | |
| ~~~~~~~~~~~~~~ | |
| By virtue of having a complete hierarchical view of all the devices in the | |
| system, exporting a complete hierarchical view to userspace becomes relatively | |
| easy. This has been accomplished by implementing a special purpose virtual | |
| file system named sysfs. | |
| Almost all mainstream Linux distros mount this filesystem automatically; you | |
| can see some variation of the following in the output of the "mount" command: | |
| $ mount | |
| ... | |
| none on /sys type sysfs (rw,noexec,nosuid,nodev) | |
| ... | |
| $ | |
| The auto-mounting of sysfs is typically accomplished by an entry similar to | |
| the following in the /etc/fstab file: | |
| none /sys sysfs defaults 0 0 | |
| or something similar in the /lib/init/fstab file on Debian-based systems: | |
| none /sys sysfs nodev,noexec,nosuid 0 0 | |
| If sysfs is not automatically mounted, you can always do it manually with: | |
| # mount -t sysfs sysfs /sys | |
| Whenever a device is inserted into the tree, a directory is created for it. | |
| This directory may be populated at each layer of discovery - the global layer, | |
| the bus layer, or the device layer. | |
| The global layer currently creates two files - 'name' and 'power'. The | |
| former only reports the name of the device. The latter reports the | |
| current power state of the device. It will also be used to set the current | |
| power state. | |
| The bus layer may also create files for the devices it finds while probing the | |
| bus. For example, the PCI layer currently creates 'irq' and 'resource' files | |
| for each PCI device. | |
| A device-specific driver may also export files in its directory to expose | |
| device-specific data or tunable interfaces. | |
| More information about the sysfs directory layout can be found in | |
| the other documents in this directory and in the file | |
| Documentation/filesystems/sysfs.txt. | |