Linux 2.6 Device Model
==================
Vijay Kumar B vijaykumar@bravegnu.org
Introduction
----------------
In the 2.4 and earlier Linux kernels, there was no unified database of what devices were present in the system, and how they were connected with each other. The implications of this are:
- The user had to grep through log messages to find out if a particular device has been detected by the kernel or not. There was no straight forward method for an application to list out what devices have been detected by the kernel, and whether a driver has
been associated with the device. - It was not possible to do proper power management, because this requires information on how the devices are connected in a system. As an example, before a USB controller is powered down, all the USB peripherals connected to that controller had to be powered
down.
To overcome these problems, in 2.5 and later kernels a framework has been provided to maintain a device model. This article describes this device model framework. The intention of this article is to provide a bird's eye view of the working of the device model framework. The
specific details of each sub-component can be obtained from various other books/articles and of course the kernel source code.
The five software components that play a major role in building and maintaining the device model are:
- the device model core -> Defines a set of structures (which form the build blocks of the device model) & functions (which update and maintain the device model). `include/linux/device.h`, drivers/base/*.c`.
- the generic bus drivers = bus / struct bus_type / bus_register(), bus_unregister()
- the bus controller drivers = device / struct device / device_register(), device_unregister()
- the device drivers = driver / struct device_driver / driver_register(), driver_unregister()
- the class drivers = class / struct class / class_register(), class_unregister()
Device Model Core
----------------------
The device model core defines a set of structures and functions. The structures form the building blocks of the device model and the functions update and maintain the device model. Some of the important structures defined by the device model core are given below.
- `struct bus_type` -> Represents busses (PCI, USB, I2C, etc.)
- `struct device` -> Represents devices (Intel AC97 audio controller, Intel PRO/100 ethernet controller, a PS/2 mouse, etc.)
- `struct device_driver` -> Represents kernel drivers that handle devices
- `struct class` -> Represents a class of devices (sound, input, graphics, etc.)
The `struct bus_type` is used to represent busses like PCI, USB, I2C, etc. The `struct device` is used to represent devices like an Intel AC97 audio controller, an Intel PRO/100 ethernet controller, a PS/2 mouse etc. The `struct device_driver` is used to represent kernel drivers that can handle specific devices. The `struct class` is used to represent a class of devices like sound, input, graphics, etc. no matter how they are connected to the system.
The device model core, among other things, defines functions to `register` and `unregister` instances of the above structures. These functions are listed below.
- `bus_register()`
- `bus_unregister()`
- `device_register()` -> 한 device에 대해 맞는 driver들을 검색
- `device_unregister()`
- `driver_register()` -> 한 driver에 대해 맞는 device들을 검색
- `driver_unregister()`
- `class_register()`
- `class_unregister()`
The files that implement the device model core are `include/linux/device.h`, drivers/base/*.c`.
Generic Bus Drivers
------------------------
Kernel이 support하는 모든 bus마다 generic bus driver 있다. Generic bus driver는 struct bus_type을 allocate하고 bus_register()를 써서 kernel의 bus type list에 register한다.
For each bus supported by the kernel, there is a generic bus driver. The generic bus driver allocates a `struct bus_type` and registers it with the kernel's list of bus types. The registration is done using `bus_register()`. (`bus_type_register()` would have been a more appropriate name!). The important fields of the bus_type structure are shown below.
-------------------------------------------------
bus_type
-- name (string)
-- !klist_devices (klist)
-- !klist_drivers (klist)
-- match (fp)
-- suspend (fp)
`-- resume (fp)
-------------------------------------------------
klist_devices는 이 bus에 존재하는 device들의 list. Bus controller driver가 device_register()를 호출함에 의해 updated됨.
Bus controller driver는 system initialization 시 bus를 scan해서 어떤 device들이 있는 지 check한 뒤 각 device 마다 device_register() 호출해서 klist_drivers를 scan해서 맞는 driver (match() 이용)를 찾는다. 그런 뒤 device를 klist_devices에 update?
Bus controller driver는 또한 gadget이 hot plugged되었을 때 (어떤 device인지 확인한 뒤) device_register() 호출해서 klist_drivers를 scan해서 각 device 마다 맞는 driver (match() 이용)를 찾는다. 그런 뒤 device를 klist_devices에 update?
klist_driver는 이 bus에 존재하는 device들을 handle할 수 있는 driver들의 list. Device driver가 스스로 initialization 할 때, driver_register()를 호출하여 자신을 등록함으로써 갱신된다.
Device driver가 kernel에 inserted되면, 이 driver는 driver_register()를 호출하여 해당 bus에 대해 klist_devices를 scan하여 이 driver가 다룰 수 있는 device들을 찾는다. 그런 뒤 driver를 klist_drivers에 update?
match()에 의해 device와 driver가 associated되는 걸 binding이라고 한다.
-------------------------------------------------
The fields marked with a `!` are internal to the device model core and should not be touched by the generic bus driver directly.
- The `name` member provides a human readable representation of the bus type, example: pci, usb, mdio.
- The `klist_devices` member is a list of devices in the system that reside on this particular type of bus. This list is updated by `device_register()` which is called when the bus is scanned for devices by the bus controller driver (= device) (during initialization or when a gadget is hot plugged.)
- The `klist_drivers` member is a list of drivers that can handle devices on that bus. This list is updated by the `driver_register()` which is called when a driver initializes itself.
- When a new gadget is plugged into the system, the bus controller driver (= device) detects the device and calls `device_register()`, the list of drivers associated with the bus is iterated over to find out if there are any drivers that can handle the device. The `match`
function provided in the `bus_type` structure is used to check if a given driver can handle a given device. - When a driver module is inserted into the kernel and the driver calls `driver_register()`, the list of devices associated with the bus is iterated over to find out if there are any devices that the driver can handle. The `match` function is used for this purpose.
When a match is found, the device is associated with the device driver. The process of associating a device with a device driver is called binding.
Given below is a sample of bus_type instantiation for the PHY management bus, taken from drivers/net/phy/mdio_bus.c`.
----------------------------------------------------------------
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
.suspend = mdio_bus_suspend,
.resume = mdio_bus_resume,
};
----------------------------------------------------------------
Apart from defining a `bus_type`, the generic bus driver defines a bus specific driver structure and a bus specific device structure. These structures extend the generic `struct device_driver` and `struct device` provided by the device model core, by adding bus specific members.
The generic bus driver provides helper functions to register and unregister device drivers that can handle devices on that bus. These helper functions wrap the generic functions provided by the device model core.
Bus Controller Drivers
---------------------------
Bus의 device driver다. 따라서, 여느 device drivers와 마찬가지로 자신을 driver_register()로 등록함. 그러나 추가적으로 자신이 다루는 bus 상에 있는 devices를 detect하여 device_register()를 이용해 등록한다. bus_type 구조체의 klist_devices list에.
새로운 Linux device driver model에서 모든 device는 bus 상에 존재하므로, 결국 bus controller driver가 모든 device를 등록한다. struct device 형태로. bus_type 구조체의 klist_devices list에.
For a specific bus type there could be many different controllers provided by different vendors. Each of these controllers needs a corresponding bus controller driver. The role of a bus controller driver in maintenance of the device model, is similar to that of any other device driver in that, it registers itself with `driver_register()`. But apart from registering itself, it also detects devices on the bus it is controlling and registers the devices on the bus using `device_register()`.
The bus controller driver is responsible for instantiating and registering instances of `struct device` with the device model core. Some of the important members of `struct device` are given below.
--------------------------------------------
device
-- bus_id (string)
-- bus (bus_type)
-- parent (device)
`-- !driver (device_driver)
--------------------------------------------
bus_id는 해당 bus 내에서 한 device의 유일한 id.
bus가 이 device가 속한 bus에 대한 pointer.
parent는 이 device를 등록한 bus controller driver에 대한 pointer.
driver는 이 device를 다룰 수 있는 driver에 대한 pointer.
--------------------------------------------
The fields marked with a `!` are internal to the device model core and should not be touched by the bus controller driver directly.
- The `bus_id` member is a unique name for the device within a bus type.
- The `bus` member is a pointer to the bus_type to which this device belongs to.
- When a device is registered by the bus controller driver, the `parent` member is pointed to the bus controller device so as to build the physical device tree.
- When a binding occurs and a driver is found that can handle the device, the `driver` member is pointed to the corresponding device driver.
As a sample bus controller driver, the bus controller driver for the PHY management bus on the MPC85xx, is available from `drivers/net/gianfar_mii.c`
Device Drivers
-----------------
모든 device driver는, driver_register()를 호출해 bus_type 구조체의 klist_drivers list에 자기 자신을 등록한다. 그 다음에 device model core가 이 driver를 한 device와 binding을 시도함.
한 device가 registered되면 (이는 곧 이 device를 handle할 수 있는 drivers가 klist_drivers에 등록된다는 말이므로) 한 특정 driver에 의해 handled될 수 있는데, 그 driver의 probe member가 하는 일이 바로 그 특정 device 하나를 위해 이 driver의 한 instance를 생성해내는 (그리고 그 device를 초기화하는) 일이다.
Every device driver registers itself with the bus_type using `driver_register()`. After which the device model core tries to bind it with a device. When a device is detected (registered) that can be handled by a particular driver, the `probe` member of the driver is called to instantiate the driver for that particular device.
Each device driver is responsible for instantiating and registering an instance of `struct device_driver` with the device model core.
The important members of `struct device_driver` is given below.
-----------------------------------------------
device_driver
-- bus (bus_type)
-- probe (fp)
-- remove (fp)
-- suspend (fp)
`-- resume (fp)
-----------------------------------------------
bus는 이 driver가 등록될 klist_drivers를 가진 bus_type 구조체에 대한 pointer.
probe는, 이 driver가 지원하는 device가 detected (이는 곧 device를 지원하는 drivers를 klist_drivers에서 찾아내는 일을 한 것 즉, binded) 될 때 마다 불리는 callback function. 이 함수는 driver 자신을 각 device 당 하나 씩 instantiate한 뒤 그 device를 initialize한다.
remove는 이 driver를 그 device로부터 unbind하기 위해 불리는 callback function. Unbinding은 device가 physically removed되거나 driver가 unloaded되거나 system이 shutdown될 때 일어난다.
-----------------------------------------------
- The `bus` member is a pointer to the bus_type to which the device driver is registered.
- The `probe` member is a callback function which is called for each device detected that is supported by the driver. The driver should instantiate itself for each device and initialize the device as well.
- The `remove` member is a callback function is called to unbind the driver from the device. This happens when the device is physically removed, when the driver is unloaded, or when the system is shutdown.
As samples of device drivers, see the PHY driver located in `drivers/net/phy/`.
Class Drivers
----------------
Class driver는 그것이 표현하는 device class들에 대해 struct class를 instantiate하여 class_register()를 통해 device model core에 등록한다.
Devices를 적당한 class에 추가하는 것은 각 해당 device driver의 책임이다.
Most users of a system are not bothered about how devices are connected in a system, but what type of devices are connected in the system. A class driver instantiates a `struct class` for the class of devices it represents and registers it with the device model core using `class_register()`. Each device driver is responsible for adding its device to the appropriate class. The important members of `struct class` is given below.
-----------------------------------------------
class
-- name (string)
`-- !devices (list)
-----------------------------------------------
devices는 이 class에 속한 device들의 list다. 이 list는 device driver들에 의해 갱신된다 (그 device driver들이 자기 자신들을 각 device들에 대해 instantiate할 때) .
-----------------------------------------------
The fields marked with a `!` mark are internal to the device model core and should not be touched by the class driver directly.
- `name` is the human readable name given to the instance of `struct class` like graphics, sound, etc.
- `devices` is a list of devices that belong to a particular instance of the class. The `devices` list is updated by the device drivers when the instantiate themselves for a device.
Conclusion
--------------
결국 이런 data structure들이 있음으로 해서, device들이 어떻게 tree 구조를 이루고 있는 지 알 수 있고, 어떤 종류의 device들이 system에 존재하는 지도 알 수 있다.
그 효과는 더 나은 power management. 그리고 system에 연결된 devices에 대한 더 나은 통찰.
With these data structures in place, a device tree of how the devices are connected in the system are available, and what types of devices are present in the system is also available. This overcomes the limitations of the 2.4 kernel, and paves way for
- better power management implementations
- better instrospection of devices connected to the system