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.

matchprobe 都会在一个 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)