前言
驱动的话我们关心几个点:
- 驱动是怎么添加到总线管理的设备链表上的?
- 注册驱动后,它是怎么和设备匹配,并最终调用驱动中的probe()函数的?
数据结构
首先看下数据结构:
struct device_driver {
const char *name;
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); //驱动的probe函数
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 dev_pm_ops *pm;
struct driver_private *p; //驱动的私有指针
};
这个结构体中我们也先只关注有注释的几个成员。bus就是我们这个驱动将要挂载到的总线(在device结构体中也有这个成员,它是bus 、dev、drv三个形成关联的桥梁),而of_match_table和probe就是我们经常在驱动中需要填充的内容。struct driver_private *p这个成员的话我们可以在驱动中灵活的使用。
驱动注册
/ * 通用驱动注册:
* 将驱动添加到相应的bus维护的驱动链表上,还有一些其它的工作.
*/
drivers/base/driver.c:
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
/* 1.首先判断驱动相关的bus->probe和drv-probe函数是否都定义了,然后发出警告。
* 这里的目的主要是不管采用哪个probe函数,确保正确的调用到probe。
*/
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);
/* 2.判断总线上是否已经有这个驱动了 */
other = driver_find(drv->name, drv->bus);
...
/* 3.bus.c:将驱动添加到总线维护的驱动链表上 */
ret = bus_add_driver(drv);
ret = driver_add_groups(drv, drv->groups);
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
return ret;
}
驱动的注册相对设备的注册来说,过程会简单很多。这个函数前两步都是做判断的,bus_add_driver才是真正的核心函数。
drivers/base/bus.c:
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus); //获取bus的类型
/* 1.分配对象及初始化 */
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
klist_init(&priv->klist_devices, NULL, NULL);
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;
/* 2. !将驱动添加到bus维护的驱动链表上 */
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
/* 3.判断是否自动调用autoprobe函数 */
if (drv->bus->p->drivers_autoprobe) {
if (driver_allows_async_probing(drv)) {
pr_debug("bus: '%s': probing driver %s asynchronously\n",
drv->bus->name, drv->name);
async_schedule(driver_attach_async, drv);
} else {
/* 4.对驱动和设备进行关联,并调用probe函数 */
error = driver_attach(drv);
...
}
}
module_add_driver(drv->owner, drv);
error = driver_create_file(drv, &driver_attr_uevent);
}
error = driver_add_groups(drv, bus->drv_groups);
...
}
在这个函数有4个主要的步骤,其它步骤2中是将驱动添加到bus维护的驱动链表上,步骤4对驱动和设备进行关联,并调用probe函数。
drivers/base/dd.c:
int driver_attach(struct device_driver *drv)
{
/* 最后一个参数是一个函数指针,可以跳进去查看 */
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
遍历总线上所有的设备,并且将和驱动进行匹配。
drivers/base/bus.c:
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,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
循环每个设备,并调用__driver_attach()函数。
drivers/base/dd.c:
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
int ret;
/* 1.driver和device进行匹配,会调用bus_type中定义的match函数 */
ret = driver_match_device(drv, dev);
device_lock(dev);
if (!dev->driver)
/* 2.probe处理 */
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
到这里之后,就和注册设备时类似,先将drv和dev进行匹配,如果匹配成功就调用驱动中的的probe()回调函数。这里不再做分析,请参考前一篇文章。