linux中 驱动框架由三部分实现:总线,驱动,设备。
驱动和 设备是两个分离的链表,分别挂载总线上。
那么驱动和设备是如何匹配后,并调用我们自己书写的驱动文件中的probe函数,从而开启驱动的其妙旅行??
当我们向内核中注册一个驱动时,会直接或间接的调用driver_resgister()来注册驱动。
设备和驱动的匹配过程 和 调用probe函数就在这里进行。
大致流程如下:
driver_register(drv)
bus_add_driver(drv)
driver_attach(drv)
__driver_attach(dev,data)
driver_match_device(drv, dev) //调用bus->match函数匹配设备与驱动
driver_probe_device(drv, dev) //匹配成功,调用probe()
really_probe(dev, drv){ //drivers/base/dd.c
...
if (dev->bus->probe) {
ret = dev->bus->probe(dev); //优先调用bus->probe
if (ret)
goto probe_failed;
} else if (drv->probe) { //其次调用drv->probe
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
...
}
当我们直接或间接调用 device_add()向内核添加设备时,也会触发 设备与驱动的匹配,并调用probe()函数。
大致流程如下:
device_add(dev)
bus_probe_device(dev)
device_initial_probe(dev)
__device_attach(dev, true)
__device_attach_driver(drv,data)
driver_match_device(drv, dev) //调用bus->match函数匹配设备与驱动
driver_probe_device(drv, dev) //匹配成功,调用probe()
really_probe(dev, drv){ //drivers/base/dd.c
...
if (dev->bus->probe) {
ret = dev->bus->probe(dev); //优先调用bus->probe
if (ret)
goto probe_failed;
} else if (drv->probe) { //其次调用drv->probe
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
...
}
当我们调用driver_resgister()时,它的整个过程代码如下:
1. driver_register(drv)
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus); //在总线中查找是否有相同的驱动存在。
if (other) {
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv); //向总线中添加新的驱动,这里进行了设备和驱动的匹配,并调用了probe.
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups); //在/sys/class系统下添加属性文件,指定特殊功能。
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD); //kobject 是sys文件系统中,一个文件的表示
return ret;
}
EXPORT_SYMBOL_GPL(driver_register);
2. bus_add_driver(drv)
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus); //总线引用计数加一
if (!bus)
return -EINVAL;
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices, NULL, NULL); //klist一个比list更安全的内核级的双向链表。
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将驱动对应的klist节点添加到klist链表的末尾。
if (drv->bus->p->drivers_autoprobe) { //在我们注册总线bus_register()中,将值置为1.
if (driver_allows_async_probing(drv)) { //主要是判断drv->probe_type,当然我们并没有给他赋值。
pr_debug("bus: '%s': probing driver %s asynchronously\n",
drv->bus->name, drv->name);
async_schedule(driver_attach_async, drv);
} else { //走这里
error = driver_attach(drv); //这里进行设备和驱动的匹配,并调用probe().
if (error)
goto out_unregister;
}
}
module_add_driver(drv->owner, drv); //module模块的添加。
error = driver_create_file(drv, &driver_attr_uevent); //添加属性文件。
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_groups(drv, bus->drv_groups);
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
__func__, drv->name);
}
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
if (error) {
/* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
__func__, drv->name);
}
}
return 0;
}
3. driver_attach(drv)
/**
* driver_attach - try to bind driver to devices. 尝试绑定 driver到总线的设备链表中。
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); //__driver_attach
}
EXPORT_SYMBOL_GPL(driver_attach);
/*
* bus_for_each_dev - device iterator. 设备迭代器
* @bus: bus type.
* @start: device to start iterating from.
* @data: data for the callback.
* @fn: function to be called for each device.
* 遍历 总线上的 设备链表,并将每一个设备作为参数,执行fn().
* 总线中的设备链表 是klist 双向链表。
*/
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus || !bus->p)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i, //klist链表和list链表还有不一样的地方。比如循环遍历
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error) //循环取出总线上的设备链表
error = fn(dev, data); //循环执行fn(),也就是__driver_attach().
klist_iter_exit(&i); //这个和上面的遍历是一组
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);
4. __driver_attach(dev,data)
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
if (!driver_match_device(drv, dev)) //调用bus-match()进行设备和驱动的匹配。
return 0; //匹配失败,直接返回,不在调用probe()函数。
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev); //这里调用驱动开发者提供的probe()函数。
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
/* 调用bus-match()进行设备和驱动的匹配。 */
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
5. driver_probe_device(drv, dev)
/**
* driver_probe_device - attempt to bind device & driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
*
* This function returns -ENODEV if the device is not registered,
* 1 if the device is bound successfully and 0 otherwise.
*
* This function must be called with @dev lock held. When called for a
* USB interface, @dev->parent lock must be held as well.
*
* If the device has a parent, runtime-resume the parent before driver probing.
*/
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //判断这个设备是否被注册过。
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
if (dev->parent)
pm_runtime_get_sync(dev->parent); //电源管理
pm_runtime_barrier(dev);
ret = really_probe(dev, drv); //这里调用了bus->probe/drv->probe. 也就是驱动开发者提供的probe().
pm_request_idle(dev);
if (dev->parent)
pm_runtime_put(dev->parent);
return ret;
}
6. really_probe(dev, drv)
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
int local_trigger_count = atomic_read(&deferred_trigger_count);
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev); //如果驱动或设备中还指定了某些pins引脚,而且指定了当前的工作状态,则将它设置为需要的工作状态。
if (ret)
goto probe_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->pm_domain && dev->pm_domain->activate) { //如果指定了电源电压域,并提供了这些激活函数。
ret = dev->pm_domain->activate(dev); //相应电源电压域激活
if (ret)
goto probe_failed;
}
if (dev->bus->probe) { //优先判断使用bus->probe()函数。
ret = dev->bus->probe(dev); //bus->probe()的内部其实最总也是调转到驱动开发者提供的probe()函数中。如果是我们自己实现的总线,记得实现这个跳转。
if (ret)
goto probe_failed;
} else if (drv->probe) { //其次判断使用drv->probe()函数。
ret = drv->probe(dev); //drv->probe()函数的一个重要任务就是跳转到驱动开发者提供的probe()函数中。
if (ret)
goto probe_failed;
}
/*
当前工作就是执行probe().当执行完毕,就需要将pins状态,再设置为默认的“default”工作状态
这里和 pinctrl_bind_pins(dev) 正好相反。
pins的工作状态 就像资源,比较紧缺,不用时,需要返回原来的状态。
这里的工作状态,在设备树中指定,例如:
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c4_xfer>;
pinctrl-1 = <&i2c4_gpio>;
*/
pinctrl_init_done(dev);
if (dev->pm_domain && dev->pm_domain->sync)
dev->pm_domain->sync(dev); //同步更新电源电压域。
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
switch (ret) {
case -EPROBE_DEFER:
/* Driver requested deferred probing */
dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
driver_deferred_probe_add(dev);
/* Did a trigger occur while probing? Need to re-trigger if yes */
if (local_trigger_count != atomic_read(&deferred_trigger_count))
driver_deferred_probe_trigger();
break;
case -ENODEV:
case -ENXIO:
pr_debug("%s: probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
break;
default:
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
至此,就调用到我们驱动开发者提供的probe().
举例:
(以spidev.c 为例)
(1)spi驱动核心spi.c中,如下指定和设置spi总线:
struct bus_type spi_bus_type = {
.name = "spi",
.dev_groups = spi_dev_groups,
.match = spi_match_device, //spi总线指定的设备和驱动的匹配方法。
.uevent = spi_uevent,
};
/* spi总线指定的设备和驱动的匹配方法。
匹配优先级:设备树匹配, acpi匹配,设备ID表匹配。
*/
static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device *spi = to_spi_device(dev);
const struct spi_driver *sdrv = to_spi_driver(drv);
/* Attempt an OF style match */
if (of_driver_match_device(dev, drv)) //设备树的匹配方法。
return 1;
/* Then try ACPI */
if (acpi_driver_match_device(dev, drv)) //apci的匹配方法。
return 1;
if (sdrv->id_table)
return !!spi_match_id(sdrv->id_table, spi); //设备ID表的匹配方法。
return strcmp(spi->modalias, drv->name) == 0;
}
(2)spi驱动框架核心spi.c提供的驱动注册:
int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
{
sdrv->driver.owner = owner;
sdrv->driver.bus = &spi_bus_type; //spi总线,这里指定了驱动和设备的匹配方式。
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe; //这里函数中指定调用spi_driver提供的probe函数。也就是驱动开发者提供的probe().
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove; //指定调用,spi_driver提供的remove函数。
if (sdrv->shutdown)
sdrv->driver.shutdown = spi_drv_shutdown; //指定嗲用 spi_driver提供的shutdown函数。
return driver_register(&sdrv->driver); //这里会进行驱动和设备的匹配,并调用sdrv->driver.probe,最总调用到驱动开发者提供的probe: spi_driver->probe().
}
EXPORT_SYMBOL_GPL(__spi_register_driver);
这里以sdrv->driver.probe = spi_drv_probe举例:
static int spi_drv_probe(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
struct spi_device *spi = to_spi_device(dev);
int ret;
ret = of_clk_set_defaults(dev->of_node, false); //不设置时钟。
if (ret)
return ret;
if (dev->of_node) {
spi->irq = of_irq_get(dev->of_node, 0); //获取中断号。
if (spi->irq == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (spi->irq < 0)
spi->irq = 0;
}
/* 电源管理操作 */
ret = dev_pm_domain_attach(dev, true);
if (ret != -EPROBE_DEFER) {
ret = sdrv->probe(spi); //执行外围提供的probe函数。及spi_driver->probe(),也就是驱动开发者提供的probe().
if (ret)
dev_pm_domain_detach(dev, true);
}
return ret;
}
(3)spidev.c 从设备驱动的驱动文件:
static int __init spidev_init(void)
{
int status;
/* Claim our 256 reserved device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* the driver which manages those device numbers.
*/
BUILD_BUG_ON(N_SPI_MINORS > 256);
status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); //使用老的字符设备接口注册字符设备。
if (status < 0)
return status;
spidev_class = class_create(THIS_MODULE, "spidev"); //创建设备类,并在/sys/class下多出spidev目录。
if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
return PTR_ERR(spidev_class);
}
/*
以上并没有触发udev/mdev在/dev目录下,创建设备节点。
还需要调用device_add() 才可以在/dev目录下创建设备节点。
spidev_spi_driver->probe()函数中调用device_add().
spi_register_driver()调用driver_register()从而触发设备和驱动的匹配,
并最终调用到了spidev_spi_driver->probe()函数。
*/
status = spi_register_driver(&spidev_spi_driver); //从设备需要注册驱动。
if (status < 0) {
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
return status;
}
module_init(spidev_init); //内核在启动中会自动执行内核中的0~7s端中的驱动出初始化,其中就包含module_init()指定的驱动初始化
整个spi中执行probe的顺序如下:
module_init(spidev_init);
spidev_init(void)
spi_register_driver(&spidev_spi_driver)
driver_register(&sdrv->driver){
driver_register()内部如何进行设备和驱动的匹配,并调用probe()在此省略,
详细请看上面的介绍。
}
。。。
really_probe(){
。。。
if (dev->bus->probe) { //spi驱动框架中没有提供这个。
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) { //spi驱动框架中提供了这个:sdrv->driver.probe = spi_drv_probe;
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
。。。
}
spi_drv_probe()
sdrv->probe(spi)
spi_driver->probe() //这个就是spidev.c中驱动开发者提供的probe()函数。
当我们调用device_add(dev)时,它的整个过程的代码如下:
1. device_add(dev)
int device_add(struct device *dev)
{
struct device *parent = NULL;
struct kobject *kobj;
struct class_interface *class_intf;
int error = -EINVAL;
struct kobject *glue_dir = NULL;
dev = get_device(dev); //引用计数加1.
if (!dev)
goto done;
if (!dev->p) {
error = device_private_init(dev);
if (error)
goto done;
}
/*
* for statically allocated devices, which should all be converted
* some day, we need to initialize the name. We prevent reading back
* the name, and force the use of dev_name()
*/
if (dev->init_name) {
dev_set_name(dev, "%s", dev->init_name); //设置设备名
dev->init_name = NULL;
}
/* subsystems can specify simple device enumeration */
if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
if (!dev_name(dev)) {
error = -EINVAL;
goto name_error;
}
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
parent = get_device(dev->parent); //该设备的父设备引用计数加一。
kobj = get_device_parent(dev, parent); //该设备的父设备对应的kobject的相关操作。
if (IS_ERR(kobj)) {
error = PTR_ERR(kobj);
goto parent_error;
}
if (kobj)
dev->kobj.parent = kobj;
/* use parent numa_node */
if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
set_dev_node(dev, dev_to_node(parent));
/* first, register with generic layer. */
/* we require the name to be set before, and pass NULL */
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //sys文件系统中kobject的添加,将当前设备对应的kobject和父设备对应的kobject进行连接。 kobject在sys文件系统中表示一个文件。
if (error) {
glue_dir = get_glue_dir(dev);
goto Error;
}
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
error = device_create_file(dev, &dev_attr_uevent); //设备属性设置。
if (error)
goto attrError;
error = device_add_class_symlinks(dev);
if (error)
goto SymlinkError;
error = device_add_attrs(dev);
if (error)
goto AttrsError;
error = bus_add_device(dev); //将这个设备添加到总线的设备链表中。
if (error)
goto BusError;
error = dpm_sysfs_add(dev);
if (error)
goto DPMError;
device_pm_add(dev);
if (MAJOR(dev->devt)) {
error = device_create_file(dev, &dev_attr_dev);
if (error)
goto DevAttrError;
error = device_create_sys_dev_entry(dev);
if (error)
goto SysEntryError;
devtmpfs_create_node(dev);
}
/* Notify clients of device addition. This call must come
* after dpm_sysfs_add() and before kobject_uevent().
*/
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_probe_device(dev); //这里进行设备和总线的驱动链表中的驱动进行匹配,并最总调用对应驱动的probe函数。
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);
if (dev->class) {
mutex_lock(&dev->class->p->mutex);
/* tie the class to the device */
klist_add_tail(&dev->knode_class,
&dev->class->p->klist_devices);
/* notify any interfaces that the device is here */
list_for_each_entry(class_intf,
&dev->class->p->interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
mutex_unlock(&dev->class->p->mutex);
}
。。。
}
EXPORT_SYMBOL_GPL(device_add);
2. bus_probe_device(dev)
/**
* bus_probe_device - probe drivers for a new device
* @dev: device to probe
*
* - Automatically probe for a driver if the bus allows it.
*/
void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
struct subsys_interface *sif;
if (!bus)
return;
if (bus->p->drivers_autoprobe) //在调用bus_register()时,被置为1. (注册总线时)
device_initial_probe(dev); //这里进行了驱动和设备的匹配,并调用匹配驱动的probe()函数。
mutex_lock(&bus->p->mutex);
list_for_each_entry(sif, &bus->p->interfaces, node)
if (sif->add_dev)
sif->add_dev(dev, sif);
mutex_unlock(&bus->p->mutex);
}
3. device_initial_probe(dev)
void device_initial_probe(struct device *dev)
{
__device_attach(dev, true);
}
4. __device_attach(dev, true)
static int __device_attach(struct device *dev, bool allow_async)
{
int ret = 0;
device_lock(dev);
/*
一般我们在添加设备时,不会指定它对应的驱动。所以这里一般是false.
当然有的设备会指定,那么一旦指定,则直接进行设备和驱动的绑定就可以
device_bind_driver()其内部也会调用到probe函数。
*/
if (dev->driver) {
if (klist_node_attached(&dev->p->knode_driver)) {
ret = 1;
goto out_unlock;
}
ret = device_bind_driver(dev); //将设备和驱动进行绑定。
if (ret == 0)
ret = 1;
else {
dev->driver = NULL;
ret = 0;
}
} else { //通常我们都会走这里,因为我们一般不给设备制定驱动,这样更灵活。
struct device_attach_data data = {
.dev = dev,
.check_async = allow_async,
.want_async = false,
};
if (dev->parent)
pm_runtime_get_sync(dev->parent);
/*
遍历总线上的 驱动链表,并将每个驱动作为参数 传递给__device_attach_driver()函数。
__device_attach_driver()函数中进行设备和驱动的匹配,并最终调用驱动的probe函数。
*/
ret = bus_for_each_drv(dev->bus, NULL, &data,
__device_attach_driver);
if (!ret && allow_async && data.have_async) {
/*
* If we could not find appropriate driver
* synchronously and we are allowed to do
* async probes and there are drivers that
* want to probe asynchronously, we'll
* try them.
*/
dev_dbg(dev, "scheduling asynchronous probe\n");
get_device(dev);
async_schedule(__device_attach_async_helper, dev);
} else {
pm_request_idle(dev);
}
if (dev->parent)
pm_runtime_put(dev->parent);
}
out_unlock:
device_unlock(dev);
return ret;
}
/*
遍历总线上的 驱动链表,并将每个驱动作为参数 传递给__device_attach_driver()函数。
__device_attach_driver()函数中进行设备和驱动的匹配,并最终调用驱动的probe函数。
*/
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *))
{
struct klist_iter i;
struct device_driver *drv;
int error = 0;
if (!bus)
return -EINVAL;
/*
klist双向链表和list链操作有所不同,比如:遍历:
klist遍历,需要三个函数/宏配合:
1.klist_iter_init_node
2.next_driver
3.klist_iter_exit
*/
klist_iter_init_node(&bus->p->klist_drivers, &i,
start ? &start->p->knode_bus : NULL);
while ((drv = next_driver(&i)) && !error)
error = fn(drv, data); //每一个获取的驱动,都执行fn()函数。
klist_iter_exit(&i);
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_drv);
5. __device_attach_driver(drv,data)
static int __device_attach_driver(struct device_driver *drv, void *_data)
{
struct device_attach_data *data = _data;
struct device *dev = data->dev;
bool async_allowed;
/*
* Check if device has already been claimed. This may
* happen with driver loading, device discovery/registration,
* and deferred probe processing happens all at once with
* multiple threads.
*/
if (dev->driver)
return -EBUSY;
if (!driver_match_device(drv, dev)) //查看设备与驱动是否匹配,调用 总线的match函数。
return 0;
async_allowed = driver_allows_async_probing(drv);
if (async_allowed)
data->have_async = true;
if (data->check_async && async_allowed != data->want_async)
return 0;
return driver_probe_device(drv, dev); //这里调用驱动开发者的probe函数。
}
6. driver_probe_device(drv, dev)
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //判断设备是否已经注册过。
return -ENODEV;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
if (dev->parent)
pm_runtime_get_sync(dev->parent);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv); //这里调用了驱动开发者提供的probe().
pm_request_idle(dev);
if (dev->parent)
pm_runtime_put(dev->parent);
return ret;
}
7. really_probe(dev, drv)
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
int local_trigger_count = atomic_read(&deferred_trigger_count);
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev); //如果驱动或设备中还指定了某些pins引脚,而且指定了当前的工作状态,则将它设置为需要的工作状态。
if (ret)
goto probe_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->pm_domain && dev->pm_domain->activate) { //如果指定了电源电压域,并提供了这些激活函数。
ret = dev->pm_domain->activate(dev); //相应电源电压域激活
if (ret)
goto probe_failed;
}
if (dev->bus->probe) { //优先判断使用bus->probe()函数。
ret = dev->bus->probe(dev); //bus->probe()的内部其实最总也是调转到驱动开发者提供的probe()函数中。如果是我们自己实现的总线,记得实现这个跳转。
if (ret)
goto probe_failed;
} else if (drv->probe) { //其次判断使用drv->probe()函数。
ret = drv->probe(dev); //drv->probe()函数的一个重要任务就是跳转到驱动开发者提供的probe()函数中。
if (ret)
goto probe_failed;
}
/*
当前工作就是执行probe().当执行完毕,就需要将pins状态,再设置为默认的“default”工作状态
这里和 pinctrl_bind_pins(dev) 正好相反。
pins的工作状态 就像资源,比较紧缺,不用时,需要返回原来的状态。
这里的工作状态,在设备树中指定,例如:
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c4_xfer>;
pinctrl-1 = <&i2c4_gpio>;
*/
pinctrl_init_done(dev);
if (dev->pm_domain && dev->pm_domain->sync)
dev->pm_domain->sync(dev); //同步更新电源电压域。
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
switch (ret) {
case -EPROBE_DEFER:
/* Driver requested deferred probing */
dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
driver_deferred_probe_add(dev);
/* Did a trigger occur while probing? Need to re-trigger if yes */
if (local_trigger_count != atomic_read(&deferred_trigger_count))
driver_deferred_probe_trigger();
break;
case -ENODEV:
case -ENXIO:
pr_debug("%s: probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
break;
default:
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
至此,就调用到设备对应驱动中提供的probe().
我们一般通过如下函数来调用device_add():
device_create()
device_create_vargs()
device_create_groups_vargs()
device_initialize(dev)
device_add(dev)
有的,则直接使用device_initialize(dev) 和 device_add(dev)来进行设备注册。