阅读这篇之前,建议先阅读我的下面这篇博客了解device_driver的数据结构和大概作用。
https://blog.csdn.net/qq_16777851/article/details/81429257
了解我的下面这篇博客可以对device部分了解清晰。同时,下面用到了device中相同的接口分析,也会略过。
https://blog.csdn.net/qq_16777851/article/details/81437352
1.driver的注册过程
/**
* driver_register - register driver with bus
* @drv: driver to register
*
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p); /* driver的总线必须要有自己的subsys,因为这个才是整个bus连接device和driver的核心 */
/* driver和bus两种都实现了下面函数,而实际最只能执行一个,所以告警说重复 */
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) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
/* 把驱动加入总线的驱动链表 */
ret = bus_add_driver(drv);
if (ret)
return ret;
/* 驱动加组 */
ret = driver_add_groups(drv, drv->groups);
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD); /* 向上增报告一个增加事件 */
return ret;
}
1.1 查找总线bus下的driver链表有没有名为name的driver
/**
* driver_find - locate driver on a bus by its name.
* @name: name of the driver.
* @bus: bus to scan for the driver.
*
* Call kset_find_obj() to iterate over list of drivers on
* a bus to find driver by name. Return driver if found.
*
* This routine provides no locking to prevent the driver it returns
* from being unregistered or unloaded while the caller is using it.
* The caller is responsible for preventing this.
*/
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); /* 在bus所管理的driver链表中,查找有没有name这个driver */
struct driver_private *priv;
if (k) {
/* Drop reference added by kset_find_obj() */
kobject_put(k); /* 把该driver的kobject引用计数减1,kset_find_obj函数对其+1了 */
priv = to_driver(k); /* 通过driver里面的kobject返回driver */
return priv->driver;
}
return NULL;
}
1.1.1 遍历kset的kobject链表中有没有名为name的kobject
/**
* kset_find_obj - search for object in kset.
* @kset: kset we're looking in.
* @name: object's name.
*
* Lock kset via @kset->subsys, and iterate over @kset->list,
* looking for a matching kobject. If matching object is found
* take a reference and return the object.
*/
struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
struct kobject *k;
struct kobject *ret = NULL;
spin_lock(&kset->list_lock);
/* 查找方法很简单,依次遍历bus的driver链表每个driver的kobject的name,如果有相同的返回对应的kobject */
list_for_each_entry(k, &kset->list, entry) {
if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get(k); /* 记住,找到的话,这里对其引用计数+1了 */
break;
}
}
spin_unlock(&kset->list_lock);
return ret;
}
上面步骤很简单,我在网上找到了一个图,可以更形象的描述上面的过程
1.2 把driver放入bus的driver链表中去
/**
* 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); /* 得到bus */
if (!bus)
return -EINVAL;
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
/* bus有自己的private,device有自己的private,driver也必须有自己的啊,他们的功能就是负责连接对方 */
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
/* 初始化klist,以及填充dricer的private里面的内容 */
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset; /* driver绑定bus(通过各自里面的privte) */
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;
/* 把driver在bus的节点,加入到bus的driver链表的最后一个 */
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
/* 前面算是已经把driver注册到对应的bus里面了 */
/* 默认所有的bus都是开启autoprobe的,除非应用层给写0,关闭了 */
if (drv->bus->p->drivers_autoprobe) {
if (driver_allows_async_probing(drv)) { /* 查看driver的probe_type支不支持异步匹配 */
pr_debug("bus: '%s': probing driver %s asynchronously\n",
drv->bus->name, drv->name);
async_schedule(driver_attach_async, drv); /* 支持异步匹配,则重开一个线程,执行driver_attach_async函数,在那个线程中执行匹配 */
} else {
error = driver_attach(drv); /* 不支持异步匹配,则直接在这个函数中匹配 */
if (error)
goto out_unregister;
}
}
module_add_driver(drv->owner, drv);
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;
out_unregister:
kobject_put(&priv->kobj);
/* drv->p is freed in driver_release() */
drv->p = NULL;
out_put_bus:
bus_put(bus);
return error;
}
1.2.1 可以看一下下面的,异步匹配和同步匹配是完全一样的代码,只不过异步匹配是多开一个线程(多核cpu有效),在里面指行匹配(这样可以不影响本cpu的效率,因为一般同一个bus上的device还是很多的,一个一个匹配要很久的。)
static void driver_attach_async(void *_drv, async_cookie_t cookie)
{
struct device_driver *drv = _drv;
int ret;
ret = driver_attach(drv);
pr_debug("bus: '%s': driver %s async attach completed: %d\n",
drv->bus->name, drv->name, ret);
}
1.2.2 通过driver匹配同一bus上的device
/**
* driver_attach - try to bind driver to devices.
* @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);
}
1.2.2.1 给出匹配函数,driver匹配同一总线下的device。注意对比上篇的bus_for_each_drv,比较异同。
/**
* 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.
*
* Iterate over @bus's list of devices, and call @fn for each,
* passing it @data. If @start is not NULL, we use that device to
* begin iterating from.
*
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
* NOTE: The device that returns a non-zero value is not retained
* in any way, nor is its refcount incremented. If the caller needs
* to retain this data, it should do so, and increment the reference
* count in the supplied callback.
*/
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;
/* 把总线上的device链表的头节点给i(注意头节点是不带有效信息的) */
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error) /* 从第一个device开始,调用fn函数,匹配driver和device */
error = fn(dev, data);
klist_iter_exit(&i); /* 结束使用klist */
return error;
}
注意:一个驱动可能匹配到多个device,所以上面的匹配除非发生错误,否则就要匹配整个链表的device.
1.2.2.2 drivace匹配device函数,对比上篇的__device_attach_driver函数,结构个功能都是一样的。
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
/* 调用bus的match函数匹配,bus的match函数不存在,则返回1 */
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
int ret;
/*
* 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.
*/
ret = driver_match_device(drv, dev); /* 在本函数上面,使用bus的match函数匹配 */
if (ret == 0) { /* 为0,没匹配到 */
/* no match */
return 0;
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
driver_deferred_probe_add(dev); /* 重新匹配 */
} else if (ret < 0) {
dev_dbg(dev, "Bus failed to match device: %d", ret); /* 总线错误 */
return ret;
} /* ret > 0 means positive match */ /* 大于0,标明正在匹配(配上了,但还有一些操作要执行) */
/* 到这里以及匹配到了,接下来就是要真正连接device和driver,以及执行probe函数了 */
if (dev->parent) /* Needed for USB */
device_lock(dev->parent); /* 设备的parent锁定,不能执行睡眠,卸载之类的操作,否则下面driver_probe_device函数如果匹配上指行probe函数,就没parent了 */
device_lock(dev); /* 要用device了,device肯定不能出乱子啊,否则删除了,这里的device接下来的操作就成野指针了 */
if (!dev->driver) /* 该device没driver,执行下句函数-----device有driver,还能匹配再到一个driver也是神了 */
driver_probe_device(drv, dev); /* 绑定device和driver,调用probe函数, */
device_unlock(dev); /* 注册好后,device就可以随意了 */
if (dev->parent)
device_unlock(dev->parent); /* */
return 0;
}
1.2.2.3 device和driver绑定,并指向probe函数
我的上一篇博客的后面有分析到,这里就不重复了。
https://blog.csdn.net/qq_16777851/article/details/81437352
总结:
1.为什么device匹配一次driver,又driver匹配一次divice?
比如:先注册的device,device在初始化的时候也绑定了bus,之后就可以主动联系自己所属bus,进一步可以通过自己所属的bus的private找到bus的driver链表,,逐个匹配同一bus上的driver。(这里我们举例是先注册的drvice,所以肯定匹配不到)
接下来注册driver,如driver,初始化的时候也绑定了bus,之后就主动联系自己所属bus,进一步可以通过自己所属的bus的private找到bus的device链表,逐个匹配同一bus上的driver。(上面device已经先于driver注册,这次肯定可以匹配到)
相反:先注册driver(driver匹配不到device),后注册device(也能匹配到driver)。
这就是为什么要即在device注册的时候匹配driver,又要在driver注册的时候匹配device的原因,因为不能确定到底驱动工程师是先注册driver还是先注册device。
2. bus有自己的subsys_private ,device有自己的device_private ,driver也有自己的driver_private,他们的功能就是负责连接对方。(下面我放出来了他们的数据结构,可以看一下,他们之间是通过klist_node 强化版的链表,互相连接起来的)
struct driver_private {
struct kobject kobj;
struct klist klist_devices; /* 一个driver可以支持多个device,所以这里用链表连接它所支持的device */
struct klist_node knode_bus; /* bus下所有driver组成一个链表,表头是bus的klist_drivers */
struct module_kobject *mkobj;
struct device_driver *driver;
};
/**
* struct device_private - structure to hold the private to the driver core portions of the device structure.
*
* @klist_children - klist containing all children of this device
* @knode_parent - node in sibling list
* @knode_driver - node in driver list
* @knode_bus - node in bus list
* @deferred_probe - entry in deferred_probe_list which is used to retry the
* binding of drivers which were unable to get all the resources needed by
* the device; typically because it depends on another driver getting
* probed first.
* @device - pointer back to the struct device that this structure is
* associated with.
*
* Nothing outside of the driver core should ever touch these fields.
*/
struct device_private {
struct klist klist_children;
struct klist_node knode_parent;
struct klist_node knode_driver; /* 一个driver可以支持多个device,该device就是靠这个节点加入到匹配到的driver的链表的 */
struct klist_node knode_bus; /* bus下所有device组成一个链表,表头是bus的klist_devices */
struct list_head deferred_probe;
struct device *device;
};
/**
* struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
*
* @subsys - the struct kset that defines this subsystem
* @devices_kset - the subsystem's 'devices' directory
* @interfaces - list of subsystem interfaces associated
* @mutex - protect the devices, and interfaces lists.
*
* @drivers_kset - the list of drivers associated
* @klist_devices - the klist to iterate over the @devices_kset
* @klist_drivers - the klist to iterate over the @drivers_kset
* @bus_notifier - the bus notifier list for anything that cares about things
* on this bus.
* @bus - pointer back to the struct bus_type that this structure is associated
* with.
*
* @glue_dirs - "glue" directory to put in-between the parent device to
* avoid namespace conflicts
* @class - pointer back to the struct class that this structure is associated
* with.
*
* This structure is the one that is the actual kobject allowing struct
* bus_type/class to be statically allocated safely. Nothing outside of the
* driver core should ever touch these fields.
*/
struct subsys_private {
struct kset subsys;
struct kset *devices_kset; /* 负责连接它下面的所有device的目录 */
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset; /* 负责连接它下面的所有driver的目录 */
struct klist klist_devices; /* 负责连接它下面的所有device的链表 */
struct klist klist_drivers; /* 负责连接它下面的所有driver的链表 */
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};