Drivers in Linux Kernel
struct device_driver
Kernel
/**
* struct device_driver - The basic device driver structure
* @name: Name of the device driver.
* @bus: The bus which the device of this driver belongs to.
* @owner: The module owner.
* @mod_name: Used for built-in modules.
* @suppress_bind_attrs: Disables bind/unbind via sysfs.
* @probe_type: Type of the probe (synchronous or asynchronous) to use.
* @of_match_table: The open firmware table.
* @acpi_match_table: The ACPI match table.
* @probe: Called to query the existence of a specific device,
* whether this driver can work with it, and bind the driver
* to a specific device.
* @sync_state: Called to sync device state to software state after all the
* state tracking consumers linked to this device (present at
* the time of late_initcall) have successfully bound to a
* driver. If the device has no consumers, this function will
* be called at late_initcall_sync level. If the device has
* consumers that are never bound to a driver, this function
* will never get called until they do.
* @remove: Called when the device is removed from the system to
* unbind a device from this driver.
* @shutdown: Called at shut-down time to quiesce the device.
* @suspend: Called to put the device to sleep mode. Usually to a
* low power state.
* @resume: Called to bring a device from sleep mode.
* @groups: Default attributes that get created by the driver core
* automatically.
* @dev_groups: Additional attributes attached to device instance once
* it is bound to the driver.
* @pm: Power management operations of the device which matched
* this driver.
* @coredump: Called when sysfs entry is written to. The device driver
* is expected to call the dev_coredump API resulting in a
* uevent.
* @p: Driver core's private data, no one other than the driver
* core can touch this.
*
* The device driver-model tracks all of the drivers known to the system.
* The main reason for this tracking is to enable the driver core to match
* up drivers with new devices. Once drivers are known objects within the
* system, however, a number of other things become possible. Device drivers
* can export information and configuration variables that are independent
* of any specific device.
*/
struct device_driver {
const char *name;
// 每一个 driver 都要有一个相关的 bus。
const struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);
void (*sync_state)(struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct attribute_group **dev_groups;
const struct dev_pm_ops *pm;
void (*coredump) (struct device *dev);
struct driver_private *p;
};
struct bus_type
/ Buses in the context of driver development
Bus 是一个假想的抽象出来的概念,并不是说真的对应一个物理上存在的总线比如说 PCIe 总线之类的。
A bus is a channel between the processor and one or more devices. All devices are connected via a bus, even if it is an internal, virtual, "platform" bus. Buses can plug into each other—a USB controller is usually a PCI device, for example. The device model represents the actual connections between buses and the devices they control.
一个 bus 上可以挂载若干个 device 和 driver。但是 bus_type
这个数据结构并没有定义一个 list 或者什么来保存这些 device 或者 driver,可能暂时还用不到。要看一个 device 或者 driver 在没在这个 bus 上可以看 device_driver->bus
或者 device->bus
。
In the Linux device model, a bus is represented by the bus_type
structure.
match
和 probe
都会在一个 device 或者 driver 被加入到 bus 中的时候被调用。区别是:
- match 是用来让 device match driver 的,当一个新的 device 加入的时候会被调用;
- probe 是用来让 driver probe device 的,当一个新的 driver 加入的时候会被调用。
注意它们名字之间的细微差别。当然上面描述也不绝对,比如在 driver attach 的时候其实也会调用 match。
struct bus_type {
const char *name;
const char *dev_name;
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
// Called, perhaps multiple times, whenever a new device or driver
// is added for this bus. It should return a positive value if the
// given device can be handled by the given driver and zero otherwise.
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);
// Called when a new device or driver add to this bus, and callback
// the specific driver's probe to initial the matched device.
int (*probe)(struct device *dev);
void (*sync_state)(struct device *dev);
void (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
int (*num_vf)(struct device *dev);
int (*dma_configure)(struct device *dev);
void (*dma_cleanup)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
bool need_parent_lock;
};
// call trace for .match and .probe
// 当添加一个新的 driver 的时候,对于已经有的所有 device,我们
// 会先 match,再 probe,这是为什么呢?
driver_register
bus_add_driver
driver_attach
// 对于 bus 上的每一个 device 都调用一遍这个新 driver
// 的 probe 的函数。
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
driver_match_device
// ##### Here we will call match #####
drv->bus->match(dev, drv)
driver_probe_device
__driver_probe_device
really_probe
call_driver_probe
// ##### Here we will call probe #####
if (dev->bus->probe)
ret = dev->bus->probe(dev);
else if (drv->probe)
ret = drv->probe(dev);
// call trace for .match
// 当加入了一个新的 device 的时候
device_add
bus_probe_device
device_initial_probe
__device_attach
// 检查所有的 driver,看看能不能 match
bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver);
driver_match_device
drv->bus->match(dev, drv)
🗞️ Recent Posts